| Index: runtime/vm/parser.cc
|
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
|
| index 9bb2f68ba7e987c51e5a2f34a01979b47120cdd0..eb3bd3d1a1a859ad017b5207326ff41c71220a5e 100644
|
| --- a/runtime/vm/parser.cc
|
| +++ b/runtime/vm/parser.cc
|
| @@ -11908,30 +11908,65 @@ bool Parser::IsInstantiatorRequired() const {
|
| return current_class().NumTypeParameters() > 0;
|
| }
|
|
|
| +// We cache computed compile-time constants in a map so we can look them
|
| +// up when the same code gets compiled again. The map key is a pair
|
| +// (script url, token position) which is encoded in an array with 2
|
| +// elements:
|
| +// - key[0] contains the canonicalized url of the script.
|
| +// - key[1] contains the token position of the constant in the script.
|
| +
|
| +// ConstantPosKey allows us to look up a constant in the map without
|
| +// allocating a key pair (array).
|
| +struct ConstantPosKey : ValueObject {
|
| + ConstantPosKey(const String& url, intptr_t pos)
|
| + : script_url(url), token_pos(pos) { }
|
| + const String& script_url;
|
| + intptr_t token_pos;
|
| +};
|
| +
|
|
|
| class ConstMapKeyEqualsTraits {
|
| public:
|
| static bool IsMatch(const Object& a, const Object& b) {
|
| - return String::Cast(a).Equals(String::Cast(b));
|
| + const Array& key1 = Array::Cast(a);
|
| + const Array& key2 = Array::Cast(b);
|
| + // Compare raw strings of script url symbol and raw smi of token positon.
|
| + return (key1.At(0) == key2.At(0)) && (key1.At(1) == key2.At(1));
|
| }
|
| - static bool IsMatch(const char* key, const Object& b) {
|
| - return String::Cast(b).Equals(key);
|
| + static bool IsMatch(const ConstantPosKey& key1, const Object& b) {
|
| + const Array& key2 = Array::Cast(b);
|
| + // Compare raw strings of script url symbol and token positon.
|
| + return (key1.script_url.raw() == key2.At(0))
|
| + && (key1.token_pos == Smi::Value(Smi::RawCast(key2.At(1))));
|
| }
|
| static uword Hash(const Object& obj) {
|
| - return String::Cast(obj).Hash();
|
| + const Array& key = Array::Cast(obj);
|
| + intptr_t url_hash = String::HashRawSymbol(String::RawCast(key.At(0)));
|
| + intptr_t pos = Smi::Value(Smi::RawCast(key.At(1)));
|
| + return HashValue(url_hash, pos);
|
| + }
|
| + static uword Hash(const ConstantPosKey& key) {
|
| + return HashValue(String::HashRawSymbol(key.script_url.raw()),
|
| + key.token_pos);
|
| }
|
| - static uword Hash(const char* key) {
|
| - return String::Hash(key, strlen(key));
|
| + // Used by CachConstantValue if a new constant is added to the map.
|
| + static RawObject* NewKey(const ConstantPosKey& key) {
|
| + const Array& key_obj = Array::Handle(Array::New(2));
|
| + key_obj.SetAt(0, key.script_url);
|
| + key_obj.SetAt(1, Smi::Handle(Smi::New(key.token_pos)));
|
| + return key_obj.raw();;
|
| + }
|
| +
|
| + private:
|
| + static uword HashValue(intptr_t url_hash, intptr_t pos) {
|
| + return url_hash * pos % (Smi::kMaxValue - 13);
|
| }
|
| };
|
| typedef UnorderedHashMap<ConstMapKeyEqualsTraits> ConstantsMap;
|
|
|
|
|
| void Parser::CacheConstantValue(intptr_t token_pos, const Instance& value) {
|
| - String& key = String::Handle(Z, script_.url());
|
| - String& suffix =
|
| - String::Handle(Z, String::NewFormatted("_%" Pd "", token_pos));
|
| - key = Symbols::FromConcat(key, suffix);
|
| + ConstantPosKey key(String::Handle(Z, script_.url()), token_pos);
|
| if (isolate()->object_store()->compile_time_constants() == Array::null()) {
|
| const intptr_t kInitialConstMapSize = 16;
|
| isolate()->object_store()->set_compile_time_constants(
|
| @@ -11939,7 +11974,7 @@ void Parser::CacheConstantValue(intptr_t token_pos, const Instance& value) {
|
| Heap::kNew)));
|
| }
|
| ConstantsMap constants(isolate()->object_store()->compile_time_constants());
|
| - constants.UpdateOrInsert(key, value);
|
| + constants.InsertNewOrGetValue(key, value);
|
| if (FLAG_compiler_stats) {
|
| isolate_->compiler_stats()->num_cached_consts = constants.NumOccupied();
|
| }
|
| @@ -11951,17 +11986,7 @@ bool Parser::GetCachedConstant(intptr_t token_pos, Instance* value) {
|
| if (isolate()->object_store()->compile_time_constants() == Array::null()) {
|
| return false;
|
| }
|
| - // We don't want to allocate anything in the heap here since this code
|
| - // is called from the optimizing compiler in the background thread. Allocate
|
| - // the key value in the zone instead.
|
| - // const char* key = Z->PrintToString("%s_%" Pd "",
|
| - // String::Handle(Z, script_.url()).ToCString(),
|
| - // token_pos);
|
| -
|
| - const String& key = String::Handle(Z,
|
| - Symbols::NewFormatted("%s_%" Pd "",
|
| - String::Handle(Z, script_.url()).ToCString(),
|
| - token_pos));
|
| + ConstantPosKey key(String::Handle(Z, script_.url()), token_pos);
|
| ConstantsMap constants(isolate()->object_store()->compile_time_constants());
|
| bool is_present = false;
|
| *value ^= constants.GetOrNull(key, &is_present);
|
|
|