08a96e13b7
In the JIT we dynamically create stubs for implicit closure invocation of fields. For AOT we only used to do this for the .call invocations (explicit closure calls). Other fields invocations would go through the slower runtime call. This CL adds invocation stubs in AOT mode for all fields that have a function type as type annotation (likely callback fields) and avoid the overhead of runtime calls. The invocation stubs are cached at receiver classes. Therefore, they are added to all subclasses of a class that defines a callback field. This speeds up Flutter's layout_bench on a Nexus 4 by 6.8%. R=rmacnak@google.com Review URL: https://codereview.chromium.org/2202773002 .
407 lines
10 KiB
C++
407 lines
10 KiB
C++
// Copyright (c) 2015, 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_PRECOMPILER_H_
|
|
#define VM_PRECOMPILER_H_
|
|
|
|
#include "vm/allocation.h"
|
|
#include "vm/hash_map.h"
|
|
#include "vm/hash_table.h"
|
|
#include "vm/object.h"
|
|
|
|
namespace dart {
|
|
|
|
// Forward declarations.
|
|
class Class;
|
|
class Error;
|
|
class Field;
|
|
class Function;
|
|
class GrowableObjectArray;
|
|
class RawError;
|
|
class SequenceNode;
|
|
class String;
|
|
|
|
class SymbolKeyValueTrait {
|
|
public:
|
|
// Typedefs needed for the DirectChainedHashMap template.
|
|
typedef const String* Key;
|
|
typedef const String* Value;
|
|
typedef const String* Pair;
|
|
|
|
static Key KeyOf(Pair kv) { return kv; }
|
|
|
|
static Value ValueOf(Pair kv) { return kv; }
|
|
|
|
static inline intptr_t Hashcode(Key key) {
|
|
return key->Hash();
|
|
}
|
|
|
|
static inline bool IsKeyEqual(Pair pair, Key key) {
|
|
return pair->raw() == key->raw();
|
|
}
|
|
};
|
|
|
|
typedef DirectChainedHashMap<SymbolKeyValueTrait> SymbolSet;
|
|
|
|
class StackmapKeyValueTrait {
|
|
public:
|
|
// Typedefs needed for the DirectChainedHashMap template.
|
|
typedef const Stackmap* Key;
|
|
typedef const Stackmap* Value;
|
|
typedef const Stackmap* Pair;
|
|
|
|
static Key KeyOf(Pair kv) { return kv; }
|
|
|
|
static Value ValueOf(Pair kv) { return kv; }
|
|
|
|
static inline intptr_t Hashcode(Key key) {
|
|
return key->PcOffset();
|
|
}
|
|
|
|
static inline bool IsKeyEqual(Pair pair, Key key) {
|
|
return pair->Equals(*key);
|
|
}
|
|
};
|
|
|
|
typedef DirectChainedHashMap<StackmapKeyValueTrait> StackmapSet;
|
|
|
|
|
|
class ArrayKeyValueTrait {
|
|
public:
|
|
// Typedefs needed for the DirectChainedHashMap template.
|
|
typedef const Array* Key;
|
|
typedef const Array* Value;
|
|
typedef const Array* Pair;
|
|
|
|
static Key KeyOf(Pair kv) { return kv; }
|
|
|
|
static Value ValueOf(Pair kv) { return kv; }
|
|
|
|
static inline intptr_t Hashcode(Key key) {
|
|
return key->Length();
|
|
}
|
|
|
|
static inline bool IsKeyEqual(Pair pair, Key key) {
|
|
if (pair->Length() != key->Length()) {
|
|
return false;
|
|
}
|
|
for (intptr_t i = 0; i < pair->Length(); i++) {
|
|
if (pair->At(i) != key->At(i)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
typedef DirectChainedHashMap<ArrayKeyValueTrait> ArraySet;
|
|
|
|
|
|
class InstructionsKeyValueTrait {
|
|
public:
|
|
// Typedefs needed for the DirectChainedHashMap template.
|
|
typedef const Instructions* Key;
|
|
typedef const Instructions* Value;
|
|
typedef const Instructions* Pair;
|
|
|
|
static Key KeyOf(Pair kv) { return kv; }
|
|
|
|
static Value ValueOf(Pair kv) { return kv; }
|
|
|
|
static inline intptr_t Hashcode(Key key) {
|
|
return key->size();
|
|
}
|
|
|
|
static inline bool IsKeyEqual(Pair pair, Key key) {
|
|
return pair->Equals(*key);
|
|
}
|
|
};
|
|
|
|
typedef DirectChainedHashMap<InstructionsKeyValueTrait> InstructionsSet;
|
|
|
|
|
|
class FunctionKeyValueTrait {
|
|
public:
|
|
// Typedefs needed for the DirectChainedHashMap template.
|
|
typedef const Function* Key;
|
|
typedef const Function* Value;
|
|
typedef const Function* Pair;
|
|
|
|
static Key KeyOf(Pair kv) { return kv; }
|
|
|
|
static Value ValueOf(Pair kv) { return kv; }
|
|
|
|
static inline intptr_t Hashcode(Key key) {
|
|
return key->token_pos().value();
|
|
}
|
|
|
|
static inline bool IsKeyEqual(Pair pair, Key key) {
|
|
return pair->raw() == key->raw();
|
|
}
|
|
};
|
|
|
|
typedef DirectChainedHashMap<FunctionKeyValueTrait> FunctionSet;
|
|
|
|
|
|
class FieldKeyValueTrait {
|
|
public:
|
|
// Typedefs needed for the DirectChainedHashMap template.
|
|
typedef const Field* Key;
|
|
typedef const Field* Value;
|
|
typedef const Field* Pair;
|
|
|
|
static Key KeyOf(Pair kv) { return kv; }
|
|
|
|
static Value ValueOf(Pair kv) { return kv; }
|
|
|
|
static inline intptr_t Hashcode(Key key) {
|
|
return key->token_pos().value();
|
|
}
|
|
|
|
static inline bool IsKeyEqual(Pair pair, Key key) {
|
|
return pair->raw() == key->raw();
|
|
}
|
|
};
|
|
|
|
typedef DirectChainedHashMap<FieldKeyValueTrait> FieldSet;
|
|
|
|
|
|
class ClassKeyValueTrait {
|
|
public:
|
|
// Typedefs needed for the DirectChainedHashMap template.
|
|
typedef const Class* Key;
|
|
typedef const Class* Value;
|
|
typedef const Class* Pair;
|
|
|
|
static Key KeyOf(Pair kv) { return kv; }
|
|
|
|
static Value ValueOf(Pair kv) { return kv; }
|
|
|
|
static inline intptr_t Hashcode(Key key) {
|
|
return key->token_pos().value();
|
|
}
|
|
|
|
static inline bool IsKeyEqual(Pair pair, Key key) {
|
|
return pair->raw() == key->raw();
|
|
}
|
|
};
|
|
|
|
typedef DirectChainedHashMap<ClassKeyValueTrait> ClassSet;
|
|
|
|
|
|
class AbstractTypeKeyValueTrait {
|
|
public:
|
|
// Typedefs needed for the DirectChainedHashMap template.
|
|
typedef const AbstractType* Key;
|
|
typedef const AbstractType* Value;
|
|
typedef const AbstractType* Pair;
|
|
|
|
static Key KeyOf(Pair kv) { return kv; }
|
|
|
|
static Value ValueOf(Pair kv) { return kv; }
|
|
|
|
static inline intptr_t Hashcode(Key key) {
|
|
return key->Hash();
|
|
}
|
|
|
|
static inline bool IsKeyEqual(Pair pair, Key key) {
|
|
return pair->raw() == key->raw();
|
|
}
|
|
};
|
|
|
|
typedef DirectChainedHashMap<AbstractTypeKeyValueTrait> AbstractTypeSet;
|
|
|
|
|
|
class TypeArgumentsKeyValueTrait {
|
|
public:
|
|
// Typedefs needed for the DirectChainedHashMap template.
|
|
typedef const TypeArguments* Key;
|
|
typedef const TypeArguments* Value;
|
|
typedef const TypeArguments* Pair;
|
|
|
|
static Key KeyOf(Pair kv) { return kv; }
|
|
|
|
static Value ValueOf(Pair kv) { return kv; }
|
|
|
|
static inline intptr_t Hashcode(Key key) {
|
|
return key->Hash();
|
|
}
|
|
|
|
static inline bool IsKeyEqual(Pair pair, Key key) {
|
|
return pair->raw() == key->raw();
|
|
}
|
|
};
|
|
|
|
typedef DirectChainedHashMap<TypeArgumentsKeyValueTrait> TypeArgumentsSet;
|
|
|
|
|
|
class InstanceKeyValueTrait {
|
|
public:
|
|
// Typedefs needed for the DirectChainedHashMap template.
|
|
typedef const Instance* Key;
|
|
typedef const Instance* Value;
|
|
typedef const Instance* Pair;
|
|
|
|
static Key KeyOf(Pair kv) { return kv; }
|
|
|
|
static Value ValueOf(Pair kv) { return kv; }
|
|
|
|
static inline intptr_t Hashcode(Key key) {
|
|
return key->GetClassId();
|
|
}
|
|
|
|
static inline bool IsKeyEqual(Pair pair, Key key) {
|
|
return pair->raw() == key->raw();
|
|
}
|
|
};
|
|
|
|
typedef DirectChainedHashMap<InstanceKeyValueTrait> InstanceSet;
|
|
|
|
|
|
class Precompiler : public ValueObject {
|
|
public:
|
|
static RawError* CompileAll(
|
|
Dart_QualifiedFunctionName embedder_entry_points[],
|
|
bool reset_fields);
|
|
|
|
static RawError* CompileFunction(Thread* thread, const Function& function);
|
|
|
|
static RawObject* EvaluateStaticInitializer(const Field& field);
|
|
static RawObject* ExecuteOnce(SequenceNode* fragment);
|
|
|
|
static RawFunction* CompileStaticInitializer(const Field& field,
|
|
bool compute_type);
|
|
|
|
private:
|
|
Precompiler(Thread* thread, bool reset_fields);
|
|
|
|
|
|
void DoCompileAll(Dart_QualifiedFunctionName embedder_entry_points[]);
|
|
void ClearAllCode();
|
|
void AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]);
|
|
void AddEntryPoints(Dart_QualifiedFunctionName entry_points[]);
|
|
void Iterate();
|
|
|
|
void AddType(const AbstractType& type);
|
|
void AddTypesOf(const Class& cls);
|
|
void AddTypesOf(const Function& function);
|
|
void AddTypeArguments(const TypeArguments& args);
|
|
void AddCalleesOf(const Function& function);
|
|
void AddConstObject(const Instance& instance);
|
|
void AddClosureCall(const ICData& call_site);
|
|
void AddField(const Field& field);
|
|
void AddFunction(const Function& function);
|
|
void AddInstantiatedClass(const Class& cls);
|
|
void AddSelector(const String& selector);
|
|
bool IsSent(const String& selector);
|
|
|
|
void ProcessFunction(const Function& function);
|
|
void CheckForNewDynamicFunctions();
|
|
void TraceConstFunctions();
|
|
void CollectCallbackFields();
|
|
|
|
void TraceForRetainedFunctions();
|
|
void DropFunctions();
|
|
void DropFields();
|
|
void TraceTypesFromRetainedClasses();
|
|
void DropTypes();
|
|
void DropTypeArguments();
|
|
void DropScriptData();
|
|
void DropClasses();
|
|
void DropLibraries();
|
|
|
|
void BindStaticCalls();
|
|
void SwitchICCalls();
|
|
void DedupStackmaps();
|
|
void DedupStackmapLists();
|
|
void DedupInstructions();
|
|
void ResetPrecompilerState();
|
|
|
|
void CollectDynamicFunctionNames();
|
|
|
|
void PrecompileStaticInitializers();
|
|
|
|
template<typename T>
|
|
class Visitor : public ValueObject {
|
|
public:
|
|
virtual ~Visitor() {}
|
|
virtual void Visit(const T& obj) = 0;
|
|
};
|
|
typedef Visitor<Function> FunctionVisitor;
|
|
typedef Visitor<Class> ClassVisitor;
|
|
|
|
void VisitFunctions(FunctionVisitor* visitor);
|
|
void VisitClasses(ClassVisitor* visitor);
|
|
|
|
void FinalizeAllClasses();
|
|
|
|
Thread* thread() const { return thread_; }
|
|
Zone* zone() const { return zone_; }
|
|
Isolate* isolate() const { return isolate_; }
|
|
|
|
Thread* thread_;
|
|
Zone* zone_;
|
|
Isolate* isolate_;
|
|
|
|
const bool reset_fields_;
|
|
|
|
bool changed_;
|
|
intptr_t function_count_;
|
|
intptr_t class_count_;
|
|
intptr_t selector_count_;
|
|
intptr_t dropped_function_count_;
|
|
intptr_t dropped_field_count_;
|
|
intptr_t dropped_class_count_;
|
|
intptr_t dropped_typearg_count_;
|
|
intptr_t dropped_type_count_;
|
|
intptr_t dropped_library_count_;
|
|
|
|
GrowableObjectArray& libraries_;
|
|
const GrowableObjectArray& pending_functions_;
|
|
SymbolSet sent_selectors_;
|
|
FunctionSet enqueued_functions_;
|
|
FieldSet fields_to_retain_;
|
|
FunctionSet functions_to_retain_;
|
|
ClassSet classes_to_retain_;
|
|
TypeArgumentsSet typeargs_to_retain_;
|
|
AbstractTypeSet types_to_retain_;
|
|
InstanceSet consts_to_retain_;
|
|
Error& error_;
|
|
};
|
|
|
|
|
|
class FunctionsTraits {
|
|
public:
|
|
static const char* Name() { return "FunctionsTraits"; }
|
|
static bool ReportStats() { return false; }
|
|
|
|
static bool IsMatch(const Object& a, const Object& b) {
|
|
Zone* zone = Thread::Current()->zone();
|
|
String& a_s = String::Handle(zone);
|
|
String& b_s = String::Handle(zone);
|
|
a_s = a.IsFunction() ? Function::Cast(a).name() : String::Cast(a).raw();
|
|
b_s = b.IsFunction() ? Function::Cast(b).name() : String::Cast(b).raw();
|
|
ASSERT(a_s.IsSymbol() && b_s.IsSymbol());
|
|
return a_s.raw() == b_s.raw();
|
|
}
|
|
static uword Hash(const Object& obj) {
|
|
if (obj.IsFunction()) {
|
|
return String::Handle(Function::Cast(obj).name()).Hash();
|
|
} else {
|
|
ASSERT(String::Cast(obj).IsSymbol());
|
|
return String::Cast(obj).Hash();
|
|
}
|
|
}
|
|
static RawObject* NewKey(const Function& function) {
|
|
return function.raw();
|
|
}
|
|
};
|
|
|
|
typedef UnorderedHashSet<FunctionsTraits> UniqueFunctionsSet;
|
|
|
|
|
|
} // namespace dart
|
|
|
|
#endif // VM_PRECOMPILER_H_
|