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
8#include "vm/class_finalizer.h"
9
10#include "vm/compiler/jit/compiler.h"
11#include "vm/flags.h"
12#include "vm/hash_table.h"
13#include "vm/heap/heap.h"
14#include "vm/interpreter.h"
15#include "vm/isolate.h"
16#include "vm/kernel_loader.h"
17#include "vm/log.h"
18#include "vm/longjump.h"
19#include "vm/object_store.h"
20#include "vm/program_visitor.h"
21#include "vm/runtime_entry.h"
22#include "vm/symbols.h"
23#include "vm/timeline.h"
24#include "vm/type_table.h"
25#include "vm/type_testing_stubs.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
33bool ClassFinalizer::AllClassesFinalized() {
34 ObjectStore* object_store = Isolate::Current()->object_store();
35 const GrowableObjectArray& classes =
36 GrowableObjectArray::Handle(object_store->pending_classes());
37 return classes.Length() == 0;
38}
39
40// Removes optimized code once we load more classes, since CHA based
41// optimizations may have become invalid.
42// Only methods which owner classes where subclasses can be invalid.
43// TODO(srdjan): Be even more precise by recording the exact CHA optimization.
44static void RemoveCHAOptimizedCode(
45 const Class& subclass,
46 const GrowableArray<intptr_t>& added_subclass_to_cids) {
47 ASSERT(FLAG_use_cha_deopt);
48 if (added_subclass_to_cids.is_empty()) {
49 return;
50 }
51 // Switch all functions' code to unoptimized.
52 const ClassTable& class_table = *Isolate::Current()->class_table();
53 Class& cls = Class::Handle();
54 for (intptr_t i = 0; i < added_subclass_to_cids.length(); i++) {
55 intptr_t cid = added_subclass_to_cids[i];
56 cls = class_table.At(cid);
57 ASSERT(!cls.IsNull());
58 cls.DisableCHAOptimizedCode(subclass);
59 }
60}
61
62static void AddSuperType(const AbstractType& type,
63 GrowableArray<intptr_t>* finalized_super_classes) {
64 ASSERT(type.HasTypeClass());
65 ASSERT(!type.IsDynamicType());
66 if (type.IsObjectType()) {
67 return;
68 }
69 const Class& cls = Class::Handle(type.type_class());
70 ASSERT(cls.is_finalized());
71 const intptr_t cid = cls.id();
72 for (intptr_t i = 0; i < finalized_super_classes->length(); i++) {
73 if ((*finalized_super_classes)[i] == cid) {
74 // Already added.
75 return;
76 }
77 }
78 finalized_super_classes->Add(cid);
79 const AbstractType& super_type = AbstractType::Handle(cls.super_type());
80 AddSuperType(super_type, finalized_super_classes);
81}
82
83// Use array instead of set since we expect very few subclassed classes
84// to occur.
85static void CollectFinalizedSuperClasses(
86 const Class& cls_,
87 GrowableArray<intptr_t>* finalized_super_classes) {
88 Class& cls = Class::Handle(cls_.raw());
89 AbstractType& super_type = Type::Handle();
90 super_type = cls.super_type();
91 if (!super_type.IsNull()) {
92 if (super_type.HasTypeClass()) {
93 cls = super_type.type_class();
94 if (cls.is_finalized()) {
95 AddSuperType(super_type, finalized_super_classes);
96 }
97 }
98 }
99}
100
101class InterfaceFinder {
102 public:
103 InterfaceFinder(Zone* zone,
104 ClassTable* class_table,
105 GrowableArray<intptr_t>* cids)
106 : class_table_(class_table),
107 array_handles_(zone),
108 class_handles_(zone),
109 type_handles_(zone),
110 cids_(cids) {}
111
112 void FindAllInterfaces(const Class& klass) {
113 // The class is implementing its own interface.
114 cids_->Add(klass.id());
115
116 ScopedHandle<Array> array(&array_handles_);
117 ScopedHandle<Class> interface_class(&class_handles_);
118 ScopedHandle<Class> current_class(&class_handles_);
119 ScopedHandle<AbstractType> type(&type_handles_);
120
121 *current_class = klass.raw();
122 while (true) {
123 // We don't care about top types.
124 const intptr_t cid = current_class->id();
125 if (cid == kObjectCid || cid == kDynamicCid || cid == kVoidCid) {
126 break;
127 }
128
129 // The class is implementing its directly declared implemented interfaces.
130 *array = klass.interfaces();
131 if (!array->IsNull()) {
132 for (intptr_t i = 0; i < array->Length(); ++i) {
133 *type ^= array->At(i);
134 *interface_class = class_table_->At(type->type_class_id());
135 FindAllInterfaces(*interface_class);
136 }
137 }
138
139 // The class is implementing its super type's interfaces.
140 *type = current_class->super_type();
141 if (type->IsNull()) break;
142 *current_class = class_table_->At(type->type_class_id());
143 }
144 }
145
146 private:
147 ClassTable* class_table_;
148 ReusableHandleStack<Array> array_handles_;
149 ReusableHandleStack<Class> class_handles_;
150 ReusableHandleStack<AbstractType> type_handles_;
151 GrowableArray<intptr_t>* cids_;
152};
153
154static void CollectImmediateSuperInterfaces(const Class& cls,
155 GrowableArray<intptr_t>* cids) {
156 const Array& interfaces = Array::Handle(cls.interfaces());
157 Class& ifc = Class::Handle();
158 AbstractType& type = AbstractType::Handle();
159 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
160 type ^= interfaces.At(i);
161 if (!type.HasTypeClass()) continue;
162 ifc = type.type_class();
163 for (intptr_t j = 0; j < cids->length(); ++j) {
164 if ((*cids)[j] == ifc.id()) {
165 // Already added.
166 return;
167 }
168 }
169 cids->Add(ifc.id());
170 }
171}
172
173// Processing ObjectStore::pending_classes_ occurs:
174// a) when bootstrap process completes (VerifyBootstrapClasses).
175// b) after the user classes are loaded (dart_api).
176bool ClassFinalizer::ProcessPendingClasses() {
177 Thread* thread = Thread::Current();
178 TIMELINE_DURATION(thread, Isolate, "ProcessPendingClasses");
179 Isolate* isolate = thread->isolate();
180 ASSERT(isolate != NULL);
181 HANDLESCOPE(thread);
182 ObjectStore* object_store = isolate->object_store();
183 const Error& error = Error::Handle(thread->zone(), thread->sticky_error());
184 if (!error.IsNull()) {
185 return false;
186 }
187 if (AllClassesFinalized()) {
188 return true;
189 }
190
191 LongJumpScope jump;
192 if (setjmp(*jump.Set()) == 0) {
193 GrowableObjectArray& class_array = GrowableObjectArray::Handle();
194 class_array = object_store->pending_classes();
195 ASSERT(!class_array.IsNull());
196 Class& cls = Class::Handle();
197
198#if defined(DEBUG)
199 for (intptr_t i = 0; i < class_array.Length(); i++) {
200 cls ^= class_array.At(i);
201 ASSERT(cls.is_declared_in_bytecode() || cls.is_declaration_loaded());
202 }
203#endif
204
205 // Finalize types in all classes.
206 for (intptr_t i = 0; i < class_array.Length(); i++) {
207 cls ^= class_array.At(i);
208 if (cls.is_declared_in_bytecode()) {
209 cls.EnsureDeclarationLoaded();
210 ASSERT(cls.is_type_finalized());
211 } else {
212 FinalizeTypesInClass(cls);
213 }
214 }
215
216 // Clear pending classes array.
217 class_array = GrowableObjectArray::New();
218 object_store->set_pending_classes(class_array);
219 VerifyImplicitFieldOffsets(); // Verification after an error may fail.
220
221 return true;
222 } else {
223 return false;
224 }
225 UNREACHABLE();
226 return true;
227}
228
229#if !defined(DART_PRECOMPILED_RUNTIME)
230void ClassFinalizer::VerifyBootstrapClasses() {
231 if (FLAG_trace_class_finalization) {
232 OS::PrintErr("VerifyBootstrapClasses START.\n");
233 }
234 ObjectStore* object_store = Isolate::Current()->object_store();
235
236 Class& cls = Class::Handle();
237#if defined(DEBUG)
238 // Basic checking.
239 cls = object_store->object_class();
240 ASSERT(Instance::InstanceSize() == cls.host_instance_size());
241 cls = object_store->integer_implementation_class();
242 ASSERT(Integer::InstanceSize() == cls.host_instance_size());
243 cls = object_store->smi_class();
244 ASSERT(Smi::InstanceSize() == cls.host_instance_size());
245 cls = object_store->mint_class();
246 ASSERT(Mint::InstanceSize() == cls.host_instance_size());
247 cls = object_store->one_byte_string_class();
248 ASSERT(OneByteString::InstanceSize() == cls.host_instance_size());
249 cls = object_store->two_byte_string_class();
250 ASSERT(TwoByteString::InstanceSize() == cls.host_instance_size());
251 cls = object_store->external_one_byte_string_class();
252 ASSERT(ExternalOneByteString::InstanceSize() == cls.host_instance_size());
253 cls = object_store->external_two_byte_string_class();
254 ASSERT(ExternalTwoByteString::InstanceSize() == cls.host_instance_size());
255 cls = object_store->double_class();
256 ASSERT(Double::InstanceSize() == cls.host_instance_size());
257 cls = object_store->bool_class();
258 ASSERT(Bool::InstanceSize() == cls.host_instance_size());
259 cls = object_store->array_class();
260 ASSERT(Array::InstanceSize() == cls.host_instance_size());
261 cls = object_store->immutable_array_class();
262 ASSERT(ImmutableArray::InstanceSize() == cls.host_instance_size());
263 cls = object_store->weak_property_class();
264 ASSERT(WeakProperty::InstanceSize() == cls.host_instance_size());
265 cls = object_store->linked_hash_map_class();
266 ASSERT(LinkedHashMap::InstanceSize() == cls.host_instance_size());
267#endif // defined(DEBUG)
268
269 // Remember the currently pending classes.
270 const GrowableObjectArray& class_array =
271 GrowableObjectArray::Handle(object_store->pending_classes());
272 for (intptr_t i = 0; i < class_array.Length(); i++) {
273 // TODO(iposva): Add real checks.
274 cls ^= class_array.At(i);
275 if (cls.is_finalized() || cls.is_prefinalized()) {
276 // Pre-finalized bootstrap classes must not define any fields.
277 ASSERT(!cls.HasInstanceFields());
278 }
279 }
280
281 // Finalize type hierarchy for types that aren't pre-finalized
282 // by Object::Init().
283 if (!ProcessPendingClasses()) {
284 // TODO(srdjan): Exit like a real VM instead.
285 const Error& err = Error::Handle(Thread::Current()->sticky_error());
286 OS::PrintErr("Could not verify bootstrap classes : %s\n",
287 err.ToErrorCString());
288 OS::Exit(255);
289 }
290 if (FLAG_trace_class_finalization) {
291 OS::PrintErr("VerifyBootstrapClasses END.\n");
292 }
293 Isolate::Current()->heap()->Verify();
294}
295#endif // !defined(DART_PRECOMPILED_RUNTIME)
296
297void ClassFinalizer::FinalizeTypeParameters(const Class& cls) {
298 if (FLAG_trace_type_finalization) {
299 THR_Print("Finalizing type parameters of '%s'\n",
300 String::Handle(cls.Name()).ToCString());
301 }
302 // The type parameter bounds are not finalized here.
303 const intptr_t offset = cls.NumTypeArguments() - cls.NumTypeParameters();
304 const TypeArguments& type_parameters =
305 TypeArguments::Handle(cls.type_parameters());
306 if (!type_parameters.IsNull()) {
307 TypeParameter& type_parameter = TypeParameter::Handle();
308 const intptr_t num_types = type_parameters.Length();
309 for (intptr_t i = 0; i < num_types; i++) {
310 type_parameter ^= type_parameters.TypeAt(i);
311 if (!type_parameter.IsFinalized()) {
312 type_parameter.set_index(type_parameter.index() + offset);
313 type_parameter.SetIsFinalized();
314 }
315 // The declaration of a type parameter is canonical.
316 ASSERT(type_parameter.IsDeclaration());
317 ASSERT(type_parameter.IsCanonical());
318 }
319 }
320}
321
322// This function reports a compilation error if the recursive 'type' T being
323// finalized is a non-contractive type, i.e. if the induced type set S of P is
324// not finite, where P is the instantiation of T with its own type parameters.
325// The induced type set S consists of the super types of any type in S as well
326// as the type arguments of any parameterized type in S.
327// The Dart Language Specification does not disallow the declaration and use of
328// non-contractive types (this may change). They are nevertheless disallowed
329// as an implementation restriction in the VM since they cause divergence.
330// A non-contractive type can be detected by looking at the queue of types
331// pending finalization that are mutually recursive with the checked type.
332void ClassFinalizer::CheckRecursiveType(const Class& cls,
333 const AbstractType& type,
334 PendingTypes* pending_types) {
335 ASSERT(pending_types != NULL);
336 Zone* zone = Thread::Current()->zone();
337 if (FLAG_trace_type_finalization) {
338 THR_Print("Checking recursive type '%s': %s\n",
339 String::Handle(type.Name()).ToCString(), type.ToCString());
340 }
341 const Class& type_cls = Class::Handle(zone, type.type_class());
342 const TypeArguments& arguments =
343 TypeArguments::Handle(zone, type.arguments());
344 // A type can only be recursive via its type arguments.
345 if (arguments.IsNull()) {
346 // However, Kernel does not keep the relation between a function type and
347 // its declaring typedef. Therefore, a typedef-declared function type may
348 // refer to the still unfinalized typedef via a type in its signature.
349 ASSERT(type.IsFunctionType());
350 return;
351 }
352 const intptr_t num_type_args = arguments.Length();
353 ASSERT(num_type_args > 0);
354 ASSERT(num_type_args == type_cls.NumTypeArguments());
355 const intptr_t num_type_params = type_cls.NumTypeParameters();
356 const intptr_t first_type_param = num_type_args - num_type_params;
357 // If the type is not generic (num_type_params == 0) or if its type parameters
358 // are instantiated, no divergence can occur. Note that if the type parameters
359 // are null, i.e. if the generic type is raw, they are considered
360 // instantiated and no divergence can occur.
361 if ((num_type_params == 0) ||
362 arguments.IsSubvectorInstantiated(first_type_param, num_type_params)) {
363 return;
364 }
365 // Consider mutually recursive and uninstantiated types pending finalization
366 // with the same type class and report an error if they are not equal in their
367 // raw form, i.e. where each class type parameter is substituted with dynamic.
368 // This test eliminates divergent types without restricting recursive types
369 // typically found in the wild.
370 TypeArguments& pending_arguments = TypeArguments::Handle(zone);
371 const intptr_t num_pending_types = pending_types->length();
372 for (intptr_t i = num_pending_types - 1; i >= 0; i--) {
373 const AbstractType& pending_type = pending_types->At(i);
374 if (FLAG_trace_type_finalization) {
375 THR_Print(" Comparing with pending type '%s': %s\n",
376 String::Handle(pending_type.Name()).ToCString(),
377 pending_type.ToCString());
378 }
379 if ((pending_type.raw() != type.raw()) && pending_type.IsType() &&
380 (pending_type.type_class() == type_cls.raw())) {
381 pending_arguments = pending_type.arguments();
382 // By using TypeEquality::kInSubtypeTest, we throw a wider net than
383 // using canonical or syntactical equality and may reject more
384 // problematic declarations.
385 if (!pending_arguments.IsSubvectorEquivalent(
386 arguments, first_type_param, num_type_params,
387 TypeEquality::kInSubtypeTest) &&
388 !pending_arguments.IsSubvectorInstantiated(first_type_param,
389 num_type_params)) {
390 const TypeArguments& instantiated_arguments = TypeArguments::Handle(
391 zone, arguments.InstantiateFrom(Object::null_type_arguments(),
392 Object::null_type_arguments(),
393 kNoneFree, Heap::kNew));
394 const TypeArguments& instantiated_pending_arguments =
395 TypeArguments::Handle(zone, pending_arguments.InstantiateFrom(
396 Object::null_type_arguments(),
397 Object::null_type_arguments(),
398 kNoneFree, Heap::kNew));
399 // By using TypeEquality::kInSubtypeTest, we throw a wider net than
400 // using canonical or syntactical equality and may reject more
401 // problematic declarations.
402 if (!instantiated_pending_arguments.IsSubvectorEquivalent(
403 instantiated_arguments, first_type_param, num_type_params,
404 TypeEquality::kInSubtypeTest)) {
405 const String& type_name = String::Handle(zone, type.Name());
406 ReportError(cls, type.token_pos(), "illegal recursive type '%s'",
407 type_name.ToCString());
408 }
409 }
410 }
411 }
412}
413
414// Expand the type arguments of the given type and finalize its full type
415// argument vector. Return the number of type arguments (0 for a raw type).
416intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
417 const Class& cls,
418 const AbstractType& type,
419 PendingTypes* pending_types) {
420 Zone* zone = Thread::Current()->zone();
421 // The type class does not need to be finalized in order to finalize the type.
422 // Also, the type parameters of the type class must be finalized.
423 Class& type_class = Class::Handle(zone, type.type_class());
424 type_class.EnsureDeclarationLoaded();
425 if (!type_class.is_type_finalized()) {
426 FinalizeTypeParameters(type_class);
427 }
428
429 // The finalized type argument vector needs num_type_arguments types.
430 const intptr_t num_type_arguments = type_class.NumTypeArguments();
431 // The class has num_type_parameters type parameters.
432 const intptr_t num_type_parameters = type_class.NumTypeParameters();
433
434 // Initialize the type argument vector.
435 // A null type argument vector indicates a raw type.
436 TypeArguments& arguments = TypeArguments::Handle(zone, type.arguments());
437 ASSERT(arguments.IsNull() || (arguments.Length() == num_type_parameters));
438
439 // Mark the type as being finalized in order to detect self reference and
440 // postpone bound checking (if required) until after all types in the graph of
441 // mutually recursive types are finalized.
442 type.SetIsBeingFinalized();
443 ASSERT(pending_types != NULL);
444 pending_types->Add(type);
445
446 // The full type argument vector consists of the type arguments of the
447 // super types of type_class, which are initialized from the parsed
448 // type arguments, followed by the parsed type arguments.
449 TypeArguments& full_arguments = TypeArguments::Handle(zone);
450 if (num_type_arguments > 0) {
451 // If no type arguments were parsed and if the super types do not prepend
452 // type arguments to the vector, we can leave the vector as null.
453 if (!arguments.IsNull() || (num_type_arguments > num_type_parameters)) {
454 full_arguments = TypeArguments::New(num_type_arguments);
455 // Copy the parsed type arguments at the correct offset in the full type
456 // argument vector.
457 const intptr_t offset = num_type_arguments - num_type_parameters;
458 AbstractType& type_arg = AbstractType::Handle(zone, Type::DynamicType());
459 // Leave the temporary type arguments at indices [0..offset[ as null.
460 for (intptr_t i = 0; i < num_type_parameters; i++) {
461 // If no type parameters were provided, a raw type is desired, so we
462 // create a vector of dynamic.
463 if (!arguments.IsNull()) {
464 type_arg = arguments.TypeAt(i);
465 // The parsed type_arg may or may not be finalized.
466 }
467 full_arguments.SetTypeAt(offset + i, type_arg);
468 }
469 // Replace the compile-time argument vector (of length zero or
470 // num_type_parameters) of this type being finalized with the still
471 // unfinalized run-time argument vector (of length num_type_arguments).
472 // This type being finalized may be recursively reached via bounds
473 // checking or type arguments of its super type.
474 type.set_arguments(full_arguments);
475 // Finalize the current type arguments of the type, which are still the
476 // parsed type arguments.
477 if (!arguments.IsNull()) {
478 for (intptr_t i = 0; i < num_type_parameters; i++) {
479 type_arg = full_arguments.TypeAt(offset + i);
480 ASSERT(!type_arg.IsBeingFinalized());
481 type_arg = FinalizeType(cls, type_arg, kFinalize, pending_types);
482 if (type_arg.IsFunctionType()) {
483 const Function& signature_function =
484 Function::Handle(zone, Type::Cast(type_arg).signature());
485 if (signature_function.IsGeneric()) {
486 const String& type_arg_name =
487 String::Handle(zone, type_arg.UserVisibleName());
488 const String& type_name =
489 String::Handle(zone, type.UserVisibleName());
490 ReportError(cls, type_arg.token_pos(),
491 "generic function type '%s' not allowed as type "
492 "argument of type '%s'",
493 type_arg_name.ToCString(), type_name.ToCString());
494 }
495 }
496 full_arguments.SetTypeAt(offset + i, type_arg);
497 }
498 }
499 if (offset > 0) {
500 TrailPtr trail = new Trail(zone, 4);
501 FinalizeTypeArguments(type_class, full_arguments, offset, pending_types,
502 trail);
503 }
504 if (full_arguments.IsRaw(0, num_type_arguments)) {
505 // The parameterized_type is raw. Set its argument vector to null, which
506 // is more efficient in type tests.
507 full_arguments = TypeArguments::null();
508 }
509 type.set_arguments(full_arguments);
510 } else {
511 ASSERT(full_arguments.IsNull()); // Use null vector for raw type.
512 }
513 }
514
515 ASSERT(full_arguments.IsNull() ||
516 !full_arguments.IsRaw(0, num_type_arguments));
517 return full_arguments.IsNull() ? 0 : full_arguments.Length();
518}
519
520// Finalize the type argument vector 'arguments' of the type defined by the
521// class 'cls' parameterized with the type arguments 'cls_args'.
522// The vector 'cls_args' is already initialized as a subvector at the correct
523// position in the passed in 'arguments' vector.
524// The subvector 'cls_args' has length cls.NumTypeParameters() and starts at
525// offset cls.NumTypeArguments() - cls.NumTypeParameters() of the 'arguments'
526// vector.
527// The type argument vector of cls may overlap the type argument vector of its
528// super class. In case of an overlap, the overlapped type arguments of the
529// super class are already initialized. The still uninitialized ones have an
530// offset smaller than 'num_uninitialized_arguments'.
531// Example 1 (without overlap):
532// Declared: class C<K, V> extends B<V> { ... }
533// class B<T> extends A<int> { ... }
534// Input: C<String, double> expressed as
535// cls = C, arguments = [dynamic, dynamic, String, double],
536// num_uninitialized_arguments = 2,
537// i.e. cls_args = [String, double], offset = 2, length = 2.
538// Output: arguments = [int, double, String, double]
539// Example 2 (with overlap):
540// Declared: class C<K, V> extends B<K> { ... }
541// class B<T> extends A<int> { ... }
542// Input: C<String, double> expressed as
543// cls = C, arguments = [dynamic, String, double],
544// num_uninitialized_arguments = 1,
545// i.e. cls_args = [String, double], offset = 1, length = 2.
546// Output: arguments = [int, String, double]
547//
548// It is too early to canonicalize the type arguments of the vector, because
549// several type argument vectors may be mutually recursive and finalized at the
550// same time. Canonicalization happens when pending types are processed.
551// The trail is required to correctly instantiate a recursive type argument
552// of the super type.
553void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
554 const TypeArguments& arguments,
555 intptr_t num_uninitialized_arguments,
556 PendingTypes* pending_types,
557 TrailPtr trail) {
558 ASSERT(arguments.Length() >= cls.NumTypeArguments());
559 if (!cls.is_type_finalized()) {
560 FinalizeTypeParameters(cls);
561 }
562 AbstractType& super_type = AbstractType::Handle(cls.super_type());
563 if (!super_type.IsNull()) {
564 const Class& super_class = Class::Handle(super_type.type_class());
565 const intptr_t num_super_type_params = super_class.NumTypeParameters();
566 const intptr_t num_super_type_args = super_class.NumTypeArguments();
567 if (!super_type.IsFinalized() && !super_type.IsBeingFinalized()) {
568 super_type = FinalizeType(cls, super_type, kFinalize, pending_types);
569 cls.set_super_type(super_type);
570 }
571 TypeArguments& super_type_args =
572 TypeArguments::Handle(super_type.arguments());
573 // Offset of super type's type parameters in cls' type argument vector.
574 const intptr_t super_offset = num_super_type_args - num_super_type_params;
575 // If the super type is raw (i.e. super_type_args is null), set to dynamic.
576 AbstractType& super_type_arg = AbstractType::Handle(Type::DynamicType());
577 for (intptr_t i = super_offset; i < num_uninitialized_arguments; i++) {
578 if (!super_type_args.IsNull()) {
579 super_type_arg = super_type_args.TypeAt(i);
580 if (!super_type_arg.IsTypeRef()) {
581 if (super_type_arg.IsBeingFinalized()) {
582 ASSERT(super_type_arg.IsType());
583 CheckRecursiveType(cls, super_type_arg, pending_types);
584 if (FLAG_trace_type_finalization) {
585 THR_Print("Creating TypeRef '%s': '%s'\n",
586 String::Handle(super_type_arg.Name()).ToCString(),
587 super_type_arg.ToCString());
588 }
589 super_type_arg = TypeRef::New(super_type_arg);
590 super_type_args.SetTypeAt(i, super_type_arg);
591 } else {
592 if (!super_type_arg.IsFinalized()) {
593 super_type_arg =
594 FinalizeType(cls, super_type_arg, kFinalize, pending_types);
595 super_type_args.SetTypeAt(i, super_type_arg);
596 // Note that super_type_arg may still not be finalized here, in
597 // which case it is a TypeRef to a legal recursive type.
598 }
599 }
600 }
601 // Instantiate super_type_arg with the current argument vector.
602 if (!super_type_arg.IsInstantiated()) {
603 if (FLAG_trace_type_finalization && super_type_arg.IsTypeRef()) {
604 AbstractType& ref_type =
605 AbstractType::Handle(TypeRef::Cast(super_type_arg).type());
606 THR_Print(
607 "Instantiating TypeRef '%s': '%s'\n"
608 " instantiator: '%s'\n",
609 String::Handle(super_type_arg.Name()).ToCString(),
610 ref_type.ToCString(), arguments.ToCString());
611 }
612 // In the typical case of an F-bounded type, the instantiation of the
613 // super_type_arg from arguments is a fixpoint. Take the shortcut.
614 // Example: class B<T>; class D<T> extends B<D<T>>;
615 // While finalizing D<T>, the super type arg D<T> (a typeref) gets
616 // instantiated from vector [T], yielding itself.
617 if (super_type_arg.IsTypeRef() &&
618 (super_type_arg.arguments() == arguments.raw())) {
619 ASSERT(super_type_arg.IsBeingFinalized());
620 arguments.SetTypeAt(i, super_type_arg);
621 continue;
622 }
623 super_type_arg = super_type_arg.InstantiateFrom(
624 arguments, Object::null_type_arguments(), kNoneFree, Heap::kOld,
625 trail);
626 if (super_type_arg.IsBeingFinalized()) {
627 // The super_type_arg was instantiated from a type being finalized.
628 // We need to finish finalizing its type arguments.
629 ASSERT(super_type_arg.IsTypeRef());
630 AbstractType& ref_super_type_arg =
631 AbstractType::Handle(TypeRef::Cast(super_type_arg).type());
632 if (FLAG_trace_type_finalization) {
633 THR_Print("Instantiated TypeRef '%s': '%s'\n",
634 String::Handle(super_type_arg.Name()).ToCString(),
635 ref_super_type_arg.ToCString());
636 }
637 CheckRecursiveType(cls, ref_super_type_arg, pending_types);
638 pending_types->Add(ref_super_type_arg);
639 const Class& super_cls =
640 Class::Handle(ref_super_type_arg.type_class());
641 const TypeArguments& super_args =
642 TypeArguments::Handle(ref_super_type_arg.arguments());
643 // Mark as finalized before finalizing to avoid cycles.
644 ref_super_type_arg.SetIsFinalized();
645 // Although the instantiator is different between cls and super_cls,
646 // we still need to pass the current instantiation trail as to avoid
647 // divergence. Finalizing the type arguments of super_cls may indeed
648 // recursively require instantiating the same type_refs already
649 // present in the trail (see issue #29949).
650 FinalizeTypeArguments(
651 super_cls, super_args,
652 super_cls.NumTypeArguments() - super_cls.NumTypeParameters(),
653 pending_types, trail);
654 if (FLAG_trace_type_finalization) {
655 THR_Print("Finalized instantiated TypeRef '%s': '%s'\n",
656 String::Handle(super_type_arg.Name()).ToCString(),
657 ref_super_type_arg.ToCString());
658 }
659 }
660 }
661 }
662 arguments.SetTypeAt(i, super_type_arg);
663 }
664 FinalizeTypeArguments(super_class, arguments, super_offset, pending_types,
665 trail);
666 }
667}
668
669AbstractTypePtr ClassFinalizer::FinalizeType(const Class& cls,
670 const AbstractType& type,
671 FinalizationKind finalization,
672 PendingTypes* pending_types) {
673 // Only the 'root' type of the graph can be canonicalized, after all depending
674 // types have been bound checked.
675 ASSERT((pending_types == NULL) || (finalization < kCanonicalize));
676 if (type.IsFinalized()) {
677 // Ensure type is canonical if canonicalization is requested.
678 if ((finalization >= kCanonicalize) && !type.IsCanonical()) {
679 return type.Canonicalize();
680 }
681 return type.raw();
682 }
683 ASSERT(finalization >= kFinalize);
684
685 if (type.IsTypeRef()) {
686 // The referenced type will be finalized later by the code that set the
687 // is_being_finalized mark bit.
688 return type.raw();
689 }
690
691 // Recursive types must be processed in FinalizeTypeArguments() and cannot be
692 // encountered here.
693 ASSERT(!type.IsBeingFinalized());
694
695 Zone* zone = Thread::Current()->zone();
696
697 if (FLAG_trace_type_finalization) {
698 THR_Print("Finalizing type '%s' for class '%s'\n",
699 String::Handle(zone, type.Name()).ToCString(),
700 String::Handle(zone, cls.Name()).ToCString());
701 }
702
703 if (type.IsTypeParameter()) {
704 const TypeParameter& type_parameter = TypeParameter::Cast(type);
705 const Class& parameterized_class =
706 Class::Handle(zone, type_parameter.parameterized_class());
707 intptr_t offset;
708 if (!parameterized_class.IsNull()) {
709 // The index must reflect the position of this type parameter in the type
710 // arguments vector of its parameterized class. The offset to add is the
711 // number of type arguments in the super type, which is equal to the
712 // difference in number of type arguments and type parameters of the
713 // parameterized class.
714 offset = parameterized_class.NumTypeArguments() -
715 parameterized_class.NumTypeParameters();
716 } else {
717 const Function& function =
718 Function::Handle(zone, type_parameter.parameterized_function());
719 ASSERT(!function.IsNull());
720 offset = function.NumParentTypeParameters();
721 }
722 type_parameter.set_index(type_parameter.index() + offset);
723 type_parameter.SetIsFinalized();
724
725 if (FLAG_trace_type_finalization) {
726 THR_Print("Done finalizing type parameter '%s' with index %" Pd "\n",
727 String::Handle(zone, type_parameter.name()).ToCString(),
728 type_parameter.index());
729 }
730
731 if (type_parameter.IsDeclaration()) {
732 // The declaration of a type parameter is canonical.
733 ASSERT(type_parameter.IsCanonical());
734 return type_parameter.raw();
735 }
736 return type_parameter.Canonicalize();
737 }
738
739 // At this point, we can only have a Type.
740 ASSERT(type.IsType());
741
742 // This type is the root type of the type graph if no pending types queue is
743 // allocated yet.
744 const bool is_root_type = pending_types == NULL;
745 if (is_root_type) {
746 pending_types = new PendingTypes(zone, 4);
747 }
748
749 const intptr_t num_expanded_type_arguments =
750 ExpandAndFinalizeTypeArguments(cls, type, pending_types);
751
752 // Self referencing types may get finalized indirectly.
753 if (!type.IsFinalized()) {
754 // If the type is a function type, we also need to finalize the types in its
755 // signature, i.e. finalize the result type and parameter types of the
756 // signature function of this function type.
757 // We do this after marking this type as finalized in order to allow a
758 // typedef function type to refer to itself via its parameter types and
759 // result type.
760 if (type.IsFunctionType()) {
761 const Type& fun_type = Type::Cast(type);
762 const Class& scope_class = Class::Handle(zone, fun_type.type_class());
763 if (scope_class.IsTypedefClass()) {
764 Function& signature =
765 Function::Handle(zone, scope_class.signature_function());
766 if (!scope_class.is_type_finalized()) {
767 FinalizeSignature(scope_class, signature, finalization);
768 }
769 // If the function type is a generic typedef, instantiate its signature
770 // from its type arguments.
771 // Example: typedef F<T> = S Function<S>(T x) has uninstantiated
772 // signature (T x) => S.
773 // The instantiated signature of F(int) becomes (int x) => S.
774 // Note that after this step, the signature of the function type is not
775 // identical to the canonical signature of the typedef class anymore.
776 if (scope_class.IsGeneric() && !signature.HasInstantiatedSignature()) {
777 if (FLAG_trace_type_finalization) {
778 THR_Print("Instantiating signature '%s' of typedef '%s'\n",
779 String::Handle(zone, signature.Signature()).ToCString(),
780 String::Handle(zone, fun_type.Name()).ToCString());
781 }
782 const TypeArguments& instantiator_type_arguments =
783 TypeArguments::Handle(zone, fun_type.arguments());
784 signature = signature.InstantiateSignatureFrom(
785 instantiator_type_arguments, Object::null_type_arguments(),
786 kNoneFree, Heap::kOld);
787 // Note that if instantiator_type_arguments contains type parameters,
788 // as in F<K>, the signature is still uninstantiated (the typedef type
789 // parameters were substituted in the signature with typedef type
790 // arguments). Note also that the function type parameters were not
791 // modified.
792 FinalizeSignature(scope_class, signature, finalization);
793 }
794 fun_type.set_signature(signature);
795 } else {
796 FinalizeSignature(cls, Function::Handle(zone, fun_type.signature()),
797 finalization);
798 }
799 }
800
801 if (FLAG_trace_type_finalization) {
802 THR_Print("Marking type '%s' as finalized for class '%s'\n",
803 String::Handle(zone, type.Name()).ToCString(),
804 String::Handle(zone, cls.Name()).ToCString());
805 }
806 // Mark the type as finalized.
807 type.SetIsFinalized();
808 }
809
810 if (FLAG_trace_type_finalization) {
811 THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
812 String::Handle(zone, type.Name()).ToCString(),
813 num_expanded_type_arguments, type.ToCString());
814 }
815
816 if (finalization >= kCanonicalize) {
817 if (FLAG_trace_type_finalization) {
818 THR_Print("Canonicalizing type '%s'\n",
819 String::Handle(zone, type.Name()).ToCString());
820 AbstractType& canonical_type =
821 AbstractType::Handle(zone, type.Canonicalize());
822 THR_Print("Done canonicalizing type '%s'\n",
823 String::Handle(zone, canonical_type.Name()).ToCString());
824 return canonical_type.raw();
825 }
826 return type.Canonicalize();
827 } else {
828 return type.raw();
829 }
830}
831
832void ClassFinalizer::FinalizeSignature(const Class& cls,
833 const Function& function,
834 FinalizationKind finalization) {
835 AbstractType& type = AbstractType::Handle();
836 AbstractType& finalized_type = AbstractType::Handle();
837 // Finalize function type parameters and their upper bounds.
838 const intptr_t num_parent_type_params = function.NumParentTypeParameters();
839 const intptr_t num_type_params = function.NumTypeParameters();
840 if (num_type_params > 0) {
841 TypeParameter& type_param = TypeParameter::Handle();
842 const TypeArguments& type_params =
843 TypeArguments::Handle(function.type_parameters());
844 for (intptr_t i = 0; i < num_type_params; i++) {
845 type_param ^= type_params.TypeAt(i);
846 if (!type_param.IsFinalized()) {
847 type_param.set_index(num_parent_type_params + i);
848 type_param.SetIsFinalized();
849 }
850 // The declaration of a type parameter is canonical.
851 ASSERT(type_param.IsDeclaration());
852 ASSERT(type_param.IsCanonical());
853 }
854 for (intptr_t i = 0; i < num_type_params; i++) {
855 type_param ^= type_params.TypeAt(i);
856 type = type_param.bound();
857 finalized_type = FinalizeType(cls, type, finalization);
858 if (finalized_type.raw() != type.raw()) {
859 type_param.set_bound(finalized_type);
860 }
861 }
862 }
863 // Finalize result type.
864 type = function.result_type();
865 finalized_type = FinalizeType(cls, type, finalization);
866 if (finalized_type.raw() != type.raw()) {
867 function.set_result_type(finalized_type);
868 }
869 // Finalize formal parameter types.
870 const intptr_t num_parameters = function.NumParameters();
871 for (intptr_t i = 0; i < num_parameters; i++) {
872 type = function.ParameterTypeAt(i);
873 finalized_type = FinalizeType(cls, type, finalization);
874 if (type.raw() != finalized_type.raw()) {
875 function.SetParameterTypeAt(i, finalized_type);
876 }
877 }
878}
879
880// Finalize the upper bounds of the type parameters of class cls.
881void ClassFinalizer::FinalizeUpperBounds(const Class& cls,
882 FinalizationKind finalization) {
883 const intptr_t num_type_params = cls.NumTypeParameters();
884 TypeParameter& type_param = TypeParameter::Handle();
885 AbstractType& bound = AbstractType::Handle();
886 const TypeArguments& type_params =
887 TypeArguments::Handle(cls.type_parameters());
888 ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
889 (type_params.Length() == num_type_params));
890 for (intptr_t i = 0; i < num_type_params; i++) {
891 type_param ^= type_params.TypeAt(i);
892 bound = type_param.bound();
893 if (bound.IsFunctionType()) {
894 const Function& signature_function =
895 Function::Handle(Type::Cast(bound).signature());
896 if (signature_function.IsGeneric()) {
897 const String& bound_name = String::Handle(bound.UserVisibleName());
898 const String& type_param_name = String::Handle(type_param.name());
899 ReportError(cls, bound.token_pos(),
900 "generic function type '%s' not allowed as bound of "
901 "class type parameter '%s'",
902 bound_name.ToCString(), type_param_name.ToCString());
903 }
904 }
905 // Bound may be finalized, but not canonical yet.
906 if (bound.IsCanonical() || bound.IsBeingFinalized()) {
907 // A bound involved in F-bounded quantification may form a cycle.
908 continue;
909 }
910 bound = FinalizeType(cls, bound, finalization);
911 type_param.set_bound(bound);
912 }
913}
914
915#if defined(TARGET_ARCH_X64)
916static bool IsPotentialExactGeneric(const AbstractType& type) {
917 // TODO(dartbug.com/34170) Investigate supporting this for fields with types
918 // that depend on type parameters of the enclosing class.
919 if (type.IsType() && !type.IsFunctionType() && !type.IsDartFunctionType() &&
920 type.IsInstantiated() && !type.IsFutureOrType()) {
921 const Class& cls = Class::Handle(type.type_class());
922 return cls.IsGeneric();
923 }
924
925 return false;
926}
927#else
928// TODO(dartbug.com/34170) Support other architectures.
929static bool IsPotentialExactGeneric(const AbstractType& type) {
930 return false;
931}
932#endif
933
934void ClassFinalizer::FinalizeMemberTypes(const Class& cls) {
935 // Note that getters and setters are explicitly listed as such in the list of
936 // functions of a class, so we do not need to consider fields as implicitly
937 // generating getters and setters.
938 // Most overriding conflicts are only static warnings, i.e. they are not
939 // reported as compile-time errors by the vm.
940 // Static warning examples are:
941 // - a static getter 'v' conflicting with an inherited instance setter 'v='.
942 // - a static setter 'v=' conflicting with an inherited instance member 'v'.
943 // - an instance member 'v' conflicting with an accessible static member 'v'
944 // or 'v=' of a super class (except that an instance method 'v' does not
945 // conflict with an accessible static setter 'v=' of a super class).
946 // The compile-time errors we report are:
947 // - a static member 'v' conflicting with an inherited instance member 'v'.
948 // - a static setter 'v=' conflicting with an inherited instance setter 'v='.
949 // - an instance method conflicting with an inherited instance field or
950 // instance getter.
951 // - an instance field or instance getter conflicting with an inherited
952 // instance method.
953
954 // Finalize type of fields and check for conflicts in super classes.
955 Isolate* isolate = Isolate::Current();
956 Zone* zone = Thread::Current()->zone();
957 Array& array = Array::Handle(zone, cls.fields());
958 Field& field = Field::Handle(zone);
959 AbstractType& type = AbstractType::Handle(zone);
960 const intptr_t num_fields = array.Length();
961 const bool track_exactness = isolate->use_field_guards();
962 for (intptr_t i = 0; i < num_fields; i++) {
963 field ^= array.At(i);
964 type = field.type();
965 type = FinalizeType(cls, type);
966 field.SetFieldType(type);
967 if (track_exactness && IsPotentialExactGeneric(type)) {
968 field.set_static_type_exactness_state(
969 StaticTypeExactnessState::Uninitialized());
970 }
971 }
972 // Finalize function signatures and check for conflicts in super classes and
973 // interfaces.
974 array = cls.functions();
975 Function& function = Function::Handle(zone);
976 const intptr_t num_functions = array.Length();
977 for (intptr_t i = 0; i < num_functions; i++) {
978 function ^= array.At(i);
979 FinalizeSignature(cls, function);
980 if (function.IsSetterFunction() || function.IsImplicitSetterFunction()) {
981 continue;
982 }
983 if (function.is_static()) {
984 if (function.IsRedirectingFactory()) {
985 Type& type = Type::Handle(zone, function.RedirectionType());
986 type ^= FinalizeType(cls, type);
987 function.SetRedirectionType(type);
988 }
989 }
990 }
991}
992
993// For a class used as an interface marks this class and all its superclasses
994// implemented.
995//
996// Does not mark its interfaces implemented because those would already be
997// marked as such.
998static void MarkImplemented(Zone* zone, const Class& iface) {
999 if (iface.is_implemented()) {
1000 return;
1001 }
1002
1003 Class& cls = Class::Handle(zone, iface.raw());
1004 AbstractType& type = AbstractType::Handle(zone);
1005
1006 while (!cls.is_implemented()) {
1007 cls.set_is_implemented();
1008
1009 type = cls.super_type();
1010 if (type.IsNull() || type.IsObjectType()) {
1011 break;
1012 }
1013 cls = type.type_class();
1014 }
1015}
1016
1017void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
1018 Thread* thread = Thread::Current();
1019 HANDLESCOPE(thread);
1020 cls.EnsureDeclarationLoaded();
1021 if (cls.is_type_finalized()) {
1022 return;
1023 }
1024 if (FLAG_trace_class_finalization) {
1025 THR_Print("Finalize types in %s\n", cls.ToCString());
1026 }
1027 // Finalize super class.
1028 Class& super_class = Class::Handle(cls.SuperClass());
1029 if (!super_class.IsNull()) {
1030 FinalizeTypesInClass(super_class);
1031 }
1032 // Finalize type parameters before finalizing the super type.
1033 FinalizeTypeParameters(cls); // May change super type while applying mixin.
1034 super_class = cls.SuperClass(); // Get again possibly changed super class.
1035 ASSERT(super_class.IsNull() || super_class.is_type_finalized());
1036 FinalizeUpperBounds(cls);
1037 // Finalize super type.
1038 AbstractType& super_type = AbstractType::Handle(cls.super_type());
1039 if (!super_type.IsNull()) {
1040 super_type = FinalizeType(cls, super_type);
1041 cls.set_super_type(super_type);
1042 }
1043 if (cls.IsTypedefClass()) {
1044 Function& signature = Function::Handle(cls.signature_function());
1045 Type& type = Type::Handle(signature.SignatureType());
1046 ASSERT(type.signature() == signature.raw());
1047 ASSERT(type.type_class() == cls.raw());
1048
1049 cls.set_is_type_finalized();
1050
1051 // Finalize the result and parameter types of the signature
1052 // function of this typedef class.
1053 FinalizeSignature(cls, signature); // Does not modify signature type.
1054 ASSERT(signature.SignatureType() == type.raw());
1055
1056 // Finalize the signature type of this typedef.
1057 type ^= FinalizeType(cls, type);
1058 ASSERT(type.type_class() == cls.raw());
1059
1060 // If a different canonical signature type is returned, update the signature
1061 // function of the typedef.
1062 signature = type.signature();
1063 signature.SetSignatureType(type);
1064 cls.set_signature_function(signature);
1065
1066 // Closure instances do not refer to this typedef as their class, so there
1067 // is no need to add this typedef class to the subclasses of _Closure.
1068 ASSERT(super_type.IsNull() || super_type.IsObjectType());
1069
1070 return;
1071 }
1072
1073 // Finalize interface types (but not necessarily interface classes).
1074 Array& interface_types = Array::Handle(cls.interfaces());
1075 AbstractType& interface_type = AbstractType::Handle();
1076 for (intptr_t i = 0; i < interface_types.Length(); i++) {
1077 interface_type ^= interface_types.At(i);
1078 interface_type = FinalizeType(cls, interface_type);
1079 interface_types.SetAt(i, interface_type);
1080 }
1081 cls.set_is_type_finalized();
1082
1083 RegisterClassInHierarchy(thread->zone(), cls);
1084}
1085
1086void ClassFinalizer::RegisterClassInHierarchy(Zone* zone, const Class& cls) {
1087 auto& type = AbstractType::Handle(zone, cls.super_type());
1088 auto& other_cls = Class::Handle(zone);
1089 // Add this class to the direct subclasses of the superclass, unless the
1090 // superclass is Object.
1091 if (!type.IsNull() && !type.IsObjectType()) {
1092 other_cls = cls.SuperClass();
1093 ASSERT(!other_cls.IsNull());
1094 other_cls.AddDirectSubclass(cls);
1095 }
1096
1097 // Add this class as an implementor to the implemented interface's type
1098 // classes.
1099 const auto& interfaces = Array::Handle(zone, cls.interfaces());
1100 const intptr_t mixin_index =
1101 cls.is_transformed_mixin_application() ? interfaces.Length() - 1 : -1;
1102 for (intptr_t i = 0; i < interfaces.Length(); ++i) {
1103 type ^= interfaces.At(i);
1104 other_cls = type.type_class();
1105 MarkImplemented(zone, other_cls);
1106 other_cls.AddDirectImplementor(cls, /* is_mixin = */ i == mixin_index);
1107 }
1108}
1109
1110void ClassFinalizer::FinalizeClass(const Class& cls) {
1111 ASSERT(cls.is_type_finalized());
1112 if (cls.is_finalized()) {
1113 return;
1114 }
1115
1116 Thread* thread = Thread::Current();
1117 HANDLESCOPE(thread);
1118
1119 if (FLAG_trace_class_finalization) {
1120 THR_Print("Finalize %s\n", cls.ToCString());
1121 }
1122
1123#if defined(SUPPORT_TIMELINE)
1124 TimelineBeginEndScope tbes(thread, Timeline::GetCompilerStream(),
1125 "FinalizeClass");
1126 if (tbes.enabled()) {
1127 tbes.SetNumArguments(1);
1128 tbes.CopyArgument(0, "class", cls.ToCString());
1129 }
1130#endif // defined(SUPPORT_TIMELINE)
1131
1132#if !defined(DART_PRECOMPILED_RUNTIME)
1133 // If loading from a kernel, make sure that the class is fully loaded.
1134 ASSERT(cls.IsTopLevel() || cls.is_declared_in_bytecode() ||
1135 (cls.kernel_offset() > 0));
1136 if (!cls.is_loaded()) {
1137 if (cls.is_declared_in_bytecode()) {
1138 kernel::BytecodeReader::FinishClassLoading(cls);
1139 } else {
1140 kernel::KernelLoader::FinishLoading(cls);
1141 }
1142 if (cls.is_finalized()) {
1143 return;
1144 }
1145 }
1146#endif // !defined(DART_PRECOMPILED_RUNTIME)
1147
1148 // Ensure super class is finalized.
1149 const Class& super = Class::Handle(cls.SuperClass());
1150 if (!super.IsNull()) {
1151 FinalizeClass(super);
1152 if (cls.is_finalized()) {
1153 return;
1154 }
1155 }
1156 // Mark as loaded and finalized.
1157 cls.Finalize();
1158 if (FLAG_print_classes) {
1159 PrintClassInformation(cls);
1160 }
1161 FinalizeMemberTypes(cls);
1162
1163 if (cls.is_enum_class()) {
1164 AllocateEnumValues(cls);
1165 }
1166
1167 // The rest of finalization for non-top-level class has to be done with
1168 // stopped mutators. It will be done by AllocateFinalizeClass. before new
1169 // instance of a class is created in GetAllocationStubForClass.
1170 if (cls.IsTopLevel()) {
1171 cls.set_is_allocate_finalized();
1172 }
1173}
1174
1175ErrorPtr ClassFinalizer::AllocateFinalizeClass(const Class& cls) {
1176 ASSERT(cls.is_finalized());
1177 if (cls.is_allocate_finalized()) {
1178 return Error::null();
1179 }
1180
1181 Thread* thread = Thread::Current();
1182 HANDLESCOPE(thread);
1183
1184 if (FLAG_trace_class_finalization) {
1185 THR_Print("Allocate finalize %s\n", cls.ToCString());
1186 }
1187
1188#if defined(SUPPORT_TIMELINE)
1189 TimelineBeginEndScope tbes(thread, Timeline::GetCompilerStream(),
1190 "AllocateFinalizeClass");
1191 if (tbes.enabled()) {
1192 tbes.SetNumArguments(1);
1193 tbes.CopyArgument(0, "class", cls.ToCString());
1194 }
1195#endif // defined(SUPPORT_TIMELINE)
1196
1197 // Run additional checks after all types are finalized.
1198 if (FLAG_use_cha_deopt && !cls.IsTopLevel()) {
1199 {
1200 GrowableArray<intptr_t> cids;
1201 CollectFinalizedSuperClasses(cls, &cids);
1202 CollectImmediateSuperInterfaces(cls, &cids);
1203 RemoveCHAOptimizedCode(cls, cids);
1204 }
1205
1206 Zone* zone = thread->zone();
1207 ClassTable* class_table = thread->isolate()->class_table();
1208 auto& interface_class = Class::Handle(zone);
1209
1210 // We scan every interface this [cls] implements and invalidate all CHA
1211 // code which depends on knowing the implementors of that interface.
1212 {
1213 GrowableArray<intptr_t> cids;
1214 InterfaceFinder finder(zone, class_table, &cids);
1215 finder.FindAllInterfaces(cls);
1216 for (intptr_t j = 0; j < cids.length(); ++j) {
1217 interface_class = class_table->At(cids[j]);
1218 interface_class.DisableCHAImplementorUsers();
1219 }
1220 }
1221 }
1222
1223 cls.set_is_allocate_finalized();
1224 return Error::null();
1225}
1226
1227ErrorPtr ClassFinalizer::LoadClassMembers(const Class& cls) {
1228 ASSERT(Thread::Current()->IsMutatorThread());
1229 LongJumpScope jump;
1230 if (setjmp(*jump.Set()) == 0) {
1231#if !defined(DART_PRECOMPILED_RUNTIME)
1232 cls.EnsureDeclarationLoaded();
1233#endif
1234 ASSERT(cls.is_type_finalized());
1235 ClassFinalizer::FinalizeClass(cls);
1236 return Error::null();
1237 } else {
1238 return Thread::Current()->StealStickyError();
1239 }
1240}
1241
1242// Allocate instances for each enumeration value, and populate the
1243// static field 'values'.
1244// By allocating the instances programmatically, we save an implicit final
1245// getter function object for each enumeration value and for the
1246// values field. We also don't have to generate the code for these getters
1247// from thin air (no source code is available).
1248void ClassFinalizer::AllocateEnumValues(const Class& enum_cls) {
1249 Thread* thread = Thread::Current();
1250 Zone* zone = thread->zone();
1251
1252 const Field& index_field =
1253 Field::Handle(zone, enum_cls.LookupInstanceField(Symbols::Index()));
1254 ASSERT(!index_field.IsNull());
1255
1256 const Field& name_field = Field::Handle(
1257 zone, enum_cls.LookupInstanceFieldAllowPrivate(Symbols::_name()));
1258 ASSERT(!name_field.IsNull());
1259
1260 const String& enum_name = String::Handle(zone, enum_cls.ScrubbedName());
1261
1262 const Array& fields = Array::Handle(zone, enum_cls.fields());
1263 Field& field = Field::Handle(zone);
1264 Instance& enum_value = Instance::Handle(zone);
1265 String& enum_ident = String::Handle(zone);
1266
1267 enum_ident =
1268 Symbols::FromConcat(thread, Symbols::_DeletedEnumPrefix(), enum_name);
1269 enum_value = Instance::New(enum_cls, Heap::kOld);
1270 enum_value.SetField(index_field, Smi::Handle(zone, Smi::New(-1)));
1271 enum_value.SetField(name_field, enum_ident);
1272 const char* error_msg = NULL;
1273 enum_value = enum_value.CheckAndCanonicalize(thread, &error_msg);
1274 ASSERT(!enum_value.IsNull());
1275 ASSERT(enum_value.IsCanonical());
1276 const Field& sentinel = Field::Handle(
1277 zone, enum_cls.LookupStaticField(Symbols::_DeletedEnumSentinel()));
1278 ASSERT(!sentinel.IsNull());
1279 sentinel.SetStaticValue(enum_value, true);
1280
1281 ASSERT(enum_cls.is_declared_in_bytecode() || enum_cls.kernel_offset() > 0);
1282 Error& error = Error::Handle(zone);
1283 for (intptr_t i = 0; i < fields.Length(); i++) {
1284 field = Field::RawCast(fields.At(i));
1285 if (!field.is_static() || !field.is_const() ||
1286 (sentinel.raw() == field.raw())) {
1287 continue;
1288 }
1289 // Hot-reload expects the static const fields to be evaluated when
1290 // performing a reload.
1291 if (!FLAG_precompiled_mode) {
1292 if (field.IsUninitialized()) {
1293 error = field.InitializeStatic();
1294 if (!error.IsNull()) {
1295 ReportError(error);
1296 }
1297 }
1298 }
1299 }
1300}
1301
1302void ClassFinalizer::PrintClassInformation(const Class& cls) {
1303 Thread* thread = Thread::Current();
1304 HANDLESCOPE(thread);
1305 const String& class_name = String::Handle(cls.Name());
1306 THR_Print("class '%s'", class_name.ToCString());
1307 const Library& library = Library::Handle(cls.library());
1308 if (!library.IsNull()) {
1309 THR_Print(" library '%s%s':\n", String::Handle(library.url()).ToCString(),
1310 String::Handle(library.private_key()).ToCString());
1311 } else {
1312 THR_Print(" (null library):\n");
1313 }
1314 const AbstractType& super_type = AbstractType::Handle(cls.super_type());
1315 if (super_type.IsNull()) {
1316 THR_Print(" Super: NULL");
1317 } else {
1318 const String& super_name = String::Handle(super_type.Name());
1319 THR_Print(" Super: %s", super_name.ToCString());
1320 }
1321 const Array& interfaces_array = Array::Handle(cls.interfaces());
1322 if (interfaces_array.Length() > 0) {
1323 THR_Print("; interfaces: ");
1324 AbstractType& interface = AbstractType::Handle();
1325 intptr_t len = interfaces_array.Length();
1326 for (intptr_t i = 0; i < len; i++) {
1327 interface ^= interfaces_array.At(i);
1328 THR_Print(" %s ", interface.ToCString());
1329 }
1330 }
1331 THR_Print("\n");
1332 const Array& functions_array = Array::Handle(cls.functions());
1333 Function& function = Function::Handle();
1334 intptr_t len = functions_array.Length();
1335 for (intptr_t i = 0; i < len; i++) {
1336 function ^= functions_array.At(i);
1337 THR_Print(" %s\n", function.ToCString());
1338 }
1339 const Array& fields_array = Array::Handle(cls.fields());
1340 Field& field = Field::Handle();
1341 len = fields_array.Length();
1342 for (intptr_t i = 0; i < len; i++) {
1343 field ^= fields_array.At(i);
1344 THR_Print(" %s\n", field.ToCString());
1345 }
1346}
1347
1348void ClassFinalizer::ReportError(const Error& error) {
1349 Report::LongJump(error);
1350 UNREACHABLE();
1351}
1352
1353void ClassFinalizer::ReportErrors(const Error& prev_error,
1354 const Class& cls,
1355 TokenPosition token_pos,
1356 const char* format,
1357 ...) {
1358 va_list args;
1359 va_start(args, format);
1360 const Script& script = Script::Handle(cls.script());
1361 Report::LongJumpV(prev_error, script, token_pos, format, args);
1362 va_end(args);
1363 UNREACHABLE();
1364}
1365
1366void ClassFinalizer::ReportError(const Class& cls,
1367 TokenPosition token_pos,
1368 const char* format,
1369 ...) {
1370 va_list args;
1371 va_start(args, format);
1372 const Script& script = Script::Handle(cls.script());
1373 Report::MessageV(Report::kError, script, token_pos, Report::AtLocation,
1374 format, args);
1375 va_end(args);
1376 UNREACHABLE();
1377}
1378
1379void ClassFinalizer::VerifyImplicitFieldOffsets() {
1380#ifdef DEBUG
1381 Thread* thread = Thread::Current();
1382 Isolate* isolate = thread->isolate();
1383
1384 if (isolate->obfuscate()) {
1385 // Field names are obfuscated.
1386 return;
1387 }
1388
1389 Zone* zone = thread->zone();
1390 const ClassTable& class_table = *(isolate->class_table());
1391 Class& cls = Class::Handle(zone);
1392 Array& fields_array = Array::Handle(zone);
1393 Field& field = Field::Handle(zone);
1394 String& name = String::Handle(zone);
1395 String& expected_name = String::Handle(zone);
1396 Error& error = Error::Handle(zone);
1397 TypeParameter& type_param = TypeParameter::Handle(zone);
1398
1399 // Now verify field offsets of '_ByteBuffer' class.
1400 cls = class_table.At(kByteBufferCid);
1401 error = cls.EnsureIsFinalized(thread);
1402 ASSERT(error.IsNull());
1403 fields_array ^= cls.fields();
1404 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields());
1405 field ^= fields_array.At(0);
1406 ASSERT(field.HostOffset() == ByteBuffer::data_offset());
1407 name ^= field.name();
1408 expected_name ^= String::New("_data");
1409 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
1410
1411 // Now verify field offsets of 'Pointer' class.
1412 cls = class_table.At(kFfiPointerCid);
1413 error = cls.EnsureIsFinalized(thread);
1414 ASSERT(error.IsNull());
1415 ASSERT(cls.NumTypeParameters() == 1);
1416 type_param ^= TypeParameter::RawCast(
1417 TypeArguments::Handle(cls.type_parameters()).TypeAt(0));
1418 ASSERT(Pointer::kNativeTypeArgPos == type_param.index());
1419#endif
1420}
1421
1422void ClassFinalizer::SortClasses() {
1423 Thread* T = Thread::Current();
1424 Zone* Z = T->zone();
1425 Isolate* I = T->isolate();
1426
1427 // Prevent background compiler from adding deferred classes or canonicalizing
1428 // new types while classes are being sorted and type hashes are modified.
1429 BackgroundCompiler::Stop(I);
1430
1431 ClassTable* table = I->class_table();
1432 intptr_t num_cids = table->NumCids();
1433
1434 std::unique_ptr<intptr_t[]> old_to_new_cid(new intptr_t[num_cids]);
1435
1436 for (intptr_t cid = 0; cid < kNumPredefinedCids; cid++) {
1437 old_to_new_cid[cid] = cid; // The predefined classes cannot change cids.
1438 }
1439 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
1440 old_to_new_cid[cid] = -1;
1441 }
1442
1443 intptr_t next_new_cid = kNumPredefinedCids;
1444 GrowableArray<intptr_t> dfs_stack;
1445 Class& cls = Class::Handle(Z);
1446 GrowableObjectArray& subclasses = GrowableObjectArray::Handle(Z);
1447
1448 // Object doesn't use its subclasses list.
1449 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
1450 if (!table->HasValidClassAt(cid)) {
1451 continue;
1452 }
1453 cls = table->At(cid);
1454 if (!cls.is_declaration_loaded()) {
1455 continue;
1456 }
1457 if (cls.SuperClass() == I->object_store()->object_class()) {
1458 dfs_stack.Add(cid);
1459 }
1460 }
1461
1462 while (dfs_stack.length() > 0) {
1463 intptr_t cid = dfs_stack.RemoveLast();
1464 ASSERT(table->HasValidClassAt(cid));
1465 cls = table->At(cid);
1466 ASSERT(!cls.IsNull());
1467 if (old_to_new_cid[cid] == -1) {
1468 old_to_new_cid[cid] = next_new_cid++;
1469 if (FLAG_trace_class_finalization) {
1470 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid],
1471 cls.ToCString(), cid);
1472 }
1473 }
1474 subclasses = cls.direct_subclasses();
1475 if (!subclasses.IsNull()) {
1476 for (intptr_t i = 0; i < subclasses.Length(); i++) {
1477 cls ^= subclasses.At(i);
1478 ASSERT(!cls.IsNull());
1479 dfs_stack.Add(cls.id());
1480 }
1481 }
1482 }
1483
1484 // Top-level classes, typedefs, patch classes, etc.
1485 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
1486 if (old_to_new_cid[cid] == -1) {
1487 old_to_new_cid[cid] = next_new_cid++;
1488 if (FLAG_trace_class_finalization && table->HasValidClassAt(cid)) {
1489 cls = table->At(cid);
1490 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid],
1491 cls.ToCString(), cid);
1492 }
1493 }
1494 }
1495 ASSERT(next_new_cid == num_cids);
1496 RemapClassIds(old_to_new_cid.get());
1497 RehashTypes(); // Types use cid's as part of their hashes.
1498 I->RehashConstants(); // Const objects use cid's as part of their hashes.
1499
1500 // Ensure any newly spawned isolate will apply this permutation map right
1501 // after kernel loading.
1502 I->group()->source()->cid_permutation_map = std::move(old_to_new_cid);
1503}
1504
1505class CidRewriteVisitor : public ObjectVisitor {
1506 public:
1507 explicit CidRewriteVisitor(intptr_t* old_to_new_cids)
1508 : old_to_new_cids_(old_to_new_cids) {}
1509
1510 intptr_t Map(intptr_t cid) {
1511 ASSERT(cid != -1);
1512 return old_to_new_cids_[cid];
1513 }
1514
1515 void VisitObject(ObjectPtr obj) {
1516 if (obj->IsClass()) {
1517 ClassPtr cls = Class::RawCast(obj);
1518 const classid_t old_cid = cls->ptr()->id_;
1519 if (ClassTable::IsTopLevelCid(old_cid)) {
1520 // We don't remap cids of top level classes.
1521 return;
1522 }
1523 cls->ptr()->id_ = Map(old_cid);
1524 } else if (obj->IsField()) {
1525 FieldPtr field = Field::RawCast(obj);
1526 field->ptr()->guarded_cid_ = Map(field->ptr()->guarded_cid_);
1527 field->ptr()->is_nullable_ = Map(field->ptr()->is_nullable_);
1528 } else if (obj->IsTypeParameter()) {
1529 TypeParameterPtr param = TypeParameter::RawCast(obj);
1530 param->ptr()->parameterized_class_id_ =
1531 Map(param->ptr()->parameterized_class_id_);
1532 } else if (obj->IsType()) {
1533 TypePtr type = Type::RawCast(obj);
1534 ObjectPtr id = type->ptr()->type_class_id_;
1535 if (!id->IsHeapObject()) {
1536 type->ptr()->type_class_id_ =
1537 Smi::New(Map(Smi::Value(Smi::RawCast(id))));
1538 }
1539 } else {
1540 intptr_t old_cid = obj->GetClassId();
1541 intptr_t new_cid = Map(old_cid);
1542 if (old_cid != new_cid) {
1543 // Don't touch objects that are unchanged. In particular, Instructions,
1544 // which are write-protected.
1545 obj->ptr()->SetClassId(new_cid);
1546 }
1547 }
1548 }
1549
1550 private:
1551 intptr_t* old_to_new_cids_;
1552};
1553
1554void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) {
1555 Thread* T = Thread::Current();
1556 IsolateGroup* IG = T->isolate_group();
1557
1558 // Code, ICData, allocation stubs have now-invalid cids.
1559 ClearAllCode();
1560
1561 {
1562 // The [HeapIterationScope] also safepoints all threads.
1563 HeapIterationScope his(T);
1564
1565 IG->shared_class_table()->Remap(old_to_new_cid);
1566 IG->ForEachIsolate(
1567 [&](Isolate* I) {
1568 I->set_remapping_cids(true);
1569
1570 // Update the class table. Do it before rewriting cids in headers, as
1571 // the heap walkers load an object's size *after* calling the visitor.
1572 I->class_table()->Remap(old_to_new_cid);
1573 },
1574 /*is_at_safepoint=*/true);
1575
1576 // Rewrite cids in headers and cids in Classes, Fields, Types and
1577 // TypeParameters.
1578 {
1579 CidRewriteVisitor visitor(old_to_new_cid);
1580 IG->heap()->VisitObjects(&visitor);
1581 }
1582
1583 IG->ForEachIsolate(
1584 [&](Isolate* I) {
1585 I->set_remapping_cids(false);
1586#if defined(DEBUG)
1587 I->class_table()->Validate();
1588#endif
1589 },
1590 /*is_at_safepoint=*/true);
1591 }
1592
1593#if defined(DEBUG)
1594 IG->heap()->Verify();
1595#endif
1596}
1597
1598// Clears the cached canonicalized hash codes for all instances which directly
1599// (or indirectly) depend on class ids.
1600//
1601// In the Dart VM heap the following instances directly use cids for the
1602// computation of canonical hash codes:
1603//
1604// * RawType (due to TypeLayout::type_class_id_)
1605// * RawTypeParameter (due to TypeParameterLayout::parameterized_class_id_)
1606//
1607// The following instances use cids for the computation of canonical hash codes
1608// indirectly:
1609//
1610// * RawTypeRef (due to TypeRefLayout::type_->type_class_id)
1611// * RawType (due to TypeLayout::signature_'s result/parameter types)
1612// * RawTypeArguments (due to type references)
1613// * RawInstance (due to instance fields)
1614// * RawArray (due to type arguments & array entries)
1615//
1616// Caching of the canonical hash codes happens for:
1617//
1618// * TypeLayout::hash_
1619// * TypeParameterLayout::hash_
1620// * TypeArgumentsLayout::hash_
1621// * RawInstance (weak table)
1622// * RawArray (weak table)
1623//
1624// No caching of canonical hash codes (i.e. it gets re-computed every time)
1625// happens for:
1626//
1627// * RawTypeRef (computed via TypeRefLayout::type_->type_class_id)
1628//
1629// Usages of canonical hash codes are:
1630//
1631// * ObjectStore::canonical_types()
1632// * ObjectStore::canonical_type_parameters()
1633// * ObjectStore::canonical_type_arguments()
1634// * Class::constants()
1635//
1636class ClearTypeHashVisitor : public ObjectVisitor {
1637 public:
1638 explicit ClearTypeHashVisitor(Zone* zone)
1639 : type_param_(TypeParameter::Handle(zone)),
1640 type_(Type::Handle(zone)),
1641 type_args_(TypeArguments::Handle(zone)) {}
1642
1643 void VisitObject(ObjectPtr obj) {
1644 if (obj->IsTypeParameter()) {
1645 type_param_ ^= obj;
1646 type_param_.SetHash(0);
1647 } else if (obj->IsType()) {
1648 type_ ^= obj;
1649 type_.SetHash(0);
1650 } else if (obj->IsTypeArguments()) {
1651 type_args_ ^= obj;
1652 type_args_.SetHash(0);
1653 }
1654 }
1655
1656 private:
1657 TypeParameter& type_param_;
1658 Type& type_;
1659 TypeArguments& type_args_;
1660};
1661
1662void ClassFinalizer::RehashTypes() {
1663 Thread* T = Thread::Current();
1664 Zone* Z = T->zone();
1665 Isolate* I = T->isolate();
1666
1667 // Clear all cached hash values.
1668 {
1669 HeapIterationScope his(T);
1670 ClearTypeHashVisitor visitor(Z);
1671 I->heap()->VisitObjects(&visitor);
1672 }
1673
1674 // Rehash the canonical Types table.
1675 ObjectStore* object_store = I->object_store();
1676 Array& types = Array::Handle(Z);
1677 Type& type = Type::Handle(Z);
1678 {
1679 CanonicalTypeSet types_table(Z, object_store->canonical_types());
1680 types = HashTables::ToArray(types_table, false);
1681 types_table.Release();
1682 }
1683
1684 intptr_t dict_size = Utils::RoundUpToPowerOfTwo(types.Length() * 4 / 3);
1685 CanonicalTypeSet types_table(
1686 Z, HashTables::New<CanonicalTypeSet>(dict_size, Heap::kOld));
1687 for (intptr_t i = 0; i < types.Length(); i++) {
1688 type ^= types.At(i);
1689 bool present = types_table.Insert(type);
1690 // Two recursive types with different topology (and hashes) may be equal.
1691 ASSERT(!present || type.IsRecursive());
1692 }
1693 object_store->set_canonical_types(types_table.Release());
1694
1695 // Rehash the canonical TypeParameters table.
1696 Array& typeparams = Array::Handle(Z);
1697 TypeParameter& typeparam = TypeParameter::Handle(Z);
1698 {
1699 CanonicalTypeParameterSet typeparams_table(
1700 Z, object_store->canonical_type_parameters());
1701 typeparams = HashTables::ToArray(typeparams_table, false);
1702 typeparams_table.Release();
1703 }
1704
1705 dict_size = Utils::RoundUpToPowerOfTwo(typeparams.Length() * 4 / 3);
1706 CanonicalTypeParameterSet typeparams_table(
1707 Z, HashTables::New<CanonicalTypeParameterSet>(dict_size, Heap::kOld));
1708 for (intptr_t i = 0; i < typeparams.Length(); i++) {
1709 typeparam ^= typeparams.At(i);
1710 bool present = typeparams_table.Insert(typeparam);
1711 ASSERT(!present);
1712 }
1713 object_store->set_canonical_type_parameters(typeparams_table.Release());
1714
1715 // Rehash the canonical TypeArguments table.
1716 Array& typeargs = Array::Handle(Z);
1717 TypeArguments& typearg = TypeArguments::Handle(Z);
1718 {
1719 CanonicalTypeArgumentsSet typeargs_table(
1720 Z, object_store->canonical_type_arguments());
1721 typeargs = HashTables::ToArray(typeargs_table, false);
1722 typeargs_table.Release();
1723 }
1724
1725 // The canonical constant tables use canonical hashcodes which can change
1726 // due to cid-renumbering.
1727 I->RehashConstants();
1728
1729 dict_size = Utils::RoundUpToPowerOfTwo(typeargs.Length() * 4 / 3);
1730 CanonicalTypeArgumentsSet typeargs_table(
1731 Z, HashTables::New<CanonicalTypeArgumentsSet>(dict_size, Heap::kOld));
1732 for (intptr_t i = 0; i < typeargs.Length(); i++) {
1733 typearg ^= typeargs.At(i);
1734 bool present = typeargs_table.Insert(typearg);
1735 // Two recursive types with different topology (and hashes) may be equal.
1736 ASSERT(!present || typearg.IsRecursive());
1737 }
1738 object_store->set_canonical_type_arguments(typeargs_table.Release());
1739}
1740
1741void ClassFinalizer::ClearAllCode(bool including_nonchanging_cids) {
1742#ifdef DART_PRECOMPILED_RUNTIME
1743 UNREACHABLE();
1744#else
1745 Thread* mutator_thread = Isolate::Current()->mutator_thread();
1746 if (mutator_thread != nullptr) {
1747 Interpreter* interpreter = mutator_thread->interpreter();
1748 if (interpreter != nullptr) {
1749 interpreter->ClearLookupCache();
1750 }
1751 }
1752
1753 auto const thread = Thread::Current();
1754 auto const isolate = thread->isolate();
1755 StackZone stack_zone(thread);
1756 HANDLESCOPE(thread);
1757 auto const zone = thread->zone();
1758
1759 class ClearCodeVisitor : public FunctionVisitor {
1760 public:
1761 ClearCodeVisitor(Zone* zone, bool force)
1762 : force_(force),
1763 bytecode_(Bytecode::Handle(zone)),
1764 pool_(ObjectPool::Handle(zone)),
1765 entry_(Object::Handle(zone)) {}
1766
1767 void VisitClass(const Class& cls) {
1768 if (force_ || cls.id() >= kNumPredefinedCids) {
1769 cls.DisableAllocationStub();
1770 }
1771 }
1772
1773 void VisitFunction(const Function& function) {
1774 bytecode_ = function.bytecode();
1775 if (!bytecode_.IsNull()) {
1776 pool_ = bytecode_.object_pool();
1777 for (intptr_t i = 0; i < pool_.Length(); i++) {
1778 ObjectPool::EntryType entry_type = pool_.TypeAt(i);
1779 if (entry_type != ObjectPool::EntryType::kTaggedObject) {
1780 continue;
1781 }
1782 entry_ = pool_.ObjectAt(i);
1783 if (entry_.IsSubtypeTestCache()) {
1784 SubtypeTestCache::Cast(entry_).Reset();
1785 }
1786 }
1787 }
1788
1789 function.ClearCode();
1790 function.ClearICDataArray();
1791 }
1792
1793 private:
1794 const bool force_;
1795 Bytecode& bytecode_;
1796 ObjectPool& pool_;
1797 Object& entry_;
1798 };
1799
1800 ClearCodeVisitor visitor(zone, including_nonchanging_cids);
1801 ProgramVisitor::WalkProgram(zone, isolate, &visitor);
1802
1803 // Apart from normal function code and allocation stubs we have two global
1804 // code objects to clear.
1805 if (including_nonchanging_cids) {
1806 auto object_store = isolate->object_store();
1807 auto& null_code = Code::Handle(zone);
1808 object_store->set_build_method_extractor_code(null_code);
1809 }
1810#endif // !DART_PRECOMPILED_RUNTIME
1811}
1812
1813} // namespace dart
1814