6bb73bd2e4
CHA::HasOverride skips non-finalized classes when looking for overrides which means that we will install incorrect code if some subclass with an override was finalized while compilation was in progress. To catch situations like this we record the number of finalized subclasses that class had when CHA made the first negative decision about it (e.g. that it has no subclasses or that it has no overrides for some function) and before installing the code we check that number of subclasses matches. Additionally renamed "leaf classes" to "guarded classes" because those classes are not necessarily leaf. R=fschneider@google.com BUG= Review URL: https://codereview.chromium.org/2002583002 .
89 lines
2.8 KiB
C++
89 lines
2.8 KiB
C++
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#ifndef VM_CHA_H_
|
|
#define VM_CHA_H_
|
|
|
|
#include "vm/allocation.h"
|
|
#include "vm/growable_array.h"
|
|
#include "vm/thread.h"
|
|
|
|
namespace dart {
|
|
|
|
class Class;
|
|
class Function;
|
|
template <typename T> class ZoneGrowableArray;
|
|
class String;
|
|
|
|
class CHA : public StackResource {
|
|
public:
|
|
explicit CHA(Thread* thread)
|
|
: StackResource(thread),
|
|
thread_(thread),
|
|
guarded_classes_(thread->zone(), 1),
|
|
previous_(thread->cha()) {
|
|
thread->set_cha(this);
|
|
}
|
|
|
|
~CHA() {
|
|
ASSERT(thread_->cha() == this);
|
|
thread_->set_cha(previous_);
|
|
}
|
|
|
|
// Returns true if the class has subclasses.
|
|
static bool HasSubclasses(const Class& cls);
|
|
bool HasSubclasses(intptr_t cid) const;
|
|
|
|
// Collect the concrete subclasses of 'cls' into 'class_ids'. Return true if
|
|
// the result is valid (may be invalid because we don't track the subclasses
|
|
// of classes allocated in the VM isolate or class Object).
|
|
bool ConcreteSubclasses(const Class& cls, GrowableArray<intptr_t> *class_ids);
|
|
|
|
// Return true if the class is implemented by some other class.
|
|
static bool IsImplemented(const Class& cls);
|
|
|
|
// Returns true if any subclass of 'cls' contains the function.
|
|
// If no override was found subclass_count would contain total count of
|
|
// finalized subclasses that CHA looked at.
|
|
// This count will be used to validate CHA decision before installing
|
|
// optimized code compiled in background.
|
|
bool HasOverride(const Class& cls,
|
|
const String& function_name,
|
|
intptr_t* subclass_count);
|
|
|
|
// Adds class 'cls' to the list of guarded classes, deoptimization occurs
|
|
// if any of those classes gets subclassed through later loaded/finalized
|
|
// libraries. Only classes that were used for CHA optimizations are added.
|
|
void AddToGuardedClasses(const Class& cls, intptr_t subclass_count);
|
|
|
|
// When compiling in background we need to check that no new finalized
|
|
// subclasses were added to guarded classes.
|
|
bool IsConsistentWithCurrentHierarchy() const;
|
|
|
|
void RegisterDependencies(const Code& code) const;
|
|
|
|
// Used for testing.
|
|
bool IsGuardedClass(intptr_t cid) const;
|
|
|
|
private:
|
|
Thread* thread_;
|
|
|
|
struct GuardedClassInfo {
|
|
Class* cls;
|
|
|
|
// Number of finalized subclasses that this class had at the moment
|
|
// when CHA made the first decision based on this class.
|
|
// Used to validate correctness of background compilation: if
|
|
// any subclasses were added we will discard compiled code.
|
|
intptr_t subclass_count;
|
|
};
|
|
|
|
GrowableArray<GuardedClassInfo> guarded_classes_;
|
|
CHA* previous_;
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#endif // VM_CHA_H_
|