Index: src/serialize.cc |
diff --git a/src/serialize.cc b/src/serialize.cc |
index be85ea600a068ed4317850721db508c1f8881680..6c0c6390a4f70e872ad45f166f493a9a8e34e534 100644 |
--- a/src/serialize.cc |
+++ b/src/serialize.cc |
@@ -417,7 +417,8 @@ class ExternalReferenceTable { |
private: |
static ExternalReferenceTable* instance_; |
- ExternalReferenceTable(); |
+ ExternalReferenceTable() : refs_(64) { PopulateTable(); } |
+ ~ExternalReferenceTable() { } |
struct ExternalReferenceEntry { |
Address address; |
@@ -425,16 +426,13 @@ class ExternalReferenceTable { |
const char* name; |
}; |
- void Add(Address address, TypeCode type, uint16_t id, const char* name) { |
- CHECK_NE(NULL, address); |
- ExternalReferenceEntry entry; |
- entry.address = address; |
- entry.code = EncodeExternal(type, id); |
- entry.name = name; |
- CHECK_NE(0, entry.code); |
- refs_.Add(entry); |
- if (id > max_id_[type]) max_id_[type] = id; |
- } |
+ void PopulateTable(); |
+ |
+ // For a few types of references, we can get their address from their id. |
+ void AddFromId(TypeCode type, uint16_t id, const char* name); |
+ |
+ // For other types of references, the caller will figure out the address. |
+ void Add(Address address, TypeCode type, uint16_t id, const char* name); |
List<ExternalReferenceEntry> refs_; |
int max_id_[kTypeCodeCount]; |
@@ -443,29 +441,80 @@ class ExternalReferenceTable { |
ExternalReferenceTable* ExternalReferenceTable::instance_ = NULL; |
+void ExternalReferenceTable::AddFromId(TypeCode type, |
+ uint16_t id, |
+ const char* name) { |
+ Address address; |
+ switch (type) { |
+ case C_BUILTIN: |
+ address = Builtins::c_function_address( |
+ static_cast<Builtins::CFunctionId>(id)); |
+ break; |
+ case BUILTIN: |
+ address = Builtins::builtin_address(static_cast<Builtins::Name>(id)); |
+ break; |
+ case RUNTIME_FUNCTION: |
+ address = Runtime::FunctionForId( |
+ static_cast<Runtime::FunctionId>(id))->entry; |
+ break; |
+ case IC_UTILITY: |
+ address = IC::AddressFromUtilityId(static_cast<IC::UtilityId>(id)); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ return; |
+ } |
+ Add(address, type, id, name); |
+} |
+ |
+void ExternalReferenceTable::Add(Address address, |
+ TypeCode type, |
+ uint16_t id, |
+ const char* name) { |
+ CHECK_NE(NULL, address); |
+ ExternalReferenceEntry entry; |
+ entry.address = address; |
+ entry.code = EncodeExternal(type, id); |
+ entry.name = name; |
+ CHECK_NE(0, entry.code); |
+ refs_.Add(entry); |
+ if (id > max_id_[type]) max_id_[type] = id; |
+} |
+ |
-ExternalReferenceTable::ExternalReferenceTable() : refs_(64) { |
+void ExternalReferenceTable::PopulateTable() { |
for (int type_code = 0; type_code < kTypeCodeCount; type_code++) { |
max_id_[type_code] = 0; |
} |
- // Define all entries in the table. |
+ // The following populates all of the different type of external references |
+ // into the ExternalReferenceTable. |
+ // |
+ // NOTE: This function was originally 100k of code. It has since been |
+ // rewritten to be mostly table driven, as the callback macro style tends to |
+ // very easily cause code bloat. Please be careful in the future when adding |
+ // new references. |
+ struct RefTableEntry { |
+ TypeCode type; |
+ uint16_t id; |
+ const char* name; |
+ }; |
+ |
+ static const RefTableEntry ref_table[] = { |
// Builtins |
#define DEF_ENTRY_C(name) \ |
- Add(Builtins::c_function_address(Builtins::c_##name), \ |
- C_BUILTIN, \ |
- Builtins::c_##name, \ |
- "Builtins::" #name); |
+ { C_BUILTIN, \ |
+ Builtins::c_##name, \ |
+ "Builtins::" #name }, |
BUILTIN_LIST_C(DEF_ENTRY_C) |
#undef DEF_ENTRY_C |
#define DEF_ENTRY_C(name) \ |
- Add(Builtins::builtin_address(Builtins::name), \ |
- BUILTIN, \ |
- Builtins::name, \ |
- "Builtins::" #name); |
+ { BUILTIN, \ |
+ Builtins::name, \ |
+ "Builtins::" #name }, |
#define DEF_ENTRY_A(name, kind, state) DEF_ENTRY_C(name) |
BUILTIN_LIST_C(DEF_ENTRY_C) |
@@ -476,24 +525,28 @@ ExternalReferenceTable::ExternalReferenceTable() : refs_(64) { |
// Runtime functions |
#define RUNTIME_ENTRY(name, nargs) \ |
- Add(Runtime::FunctionForId(Runtime::k##name)->entry, \ |
- RUNTIME_FUNCTION, \ |
- Runtime::k##name, \ |
- "Runtime::" #name); |
+ { RUNTIME_FUNCTION, \ |
+ Runtime::k##name, \ |
+ "Runtime::" #name }, |
RUNTIME_FUNCTION_LIST(RUNTIME_ENTRY) |
#undef RUNTIME_ENTRY |
// IC utilities |
#define IC_ENTRY(name) \ |
- Add(IC::AddressFromUtilityId(IC::k##name), \ |
- IC_UTILITY, \ |
- IC::k##name, \ |
- "IC::" #name); |
+ { IC_UTILITY, \ |
+ IC::k##name, \ |
+ "IC::" #name }, |
IC_UTIL_LIST(IC_ENTRY) |
#undef IC_ENTRY |
+ }; // end of ref_table[]. |
+ |
+ for (size_t i = 0; i < ARRAY_SIZE(ref_table); ++i) { |
+ AddFromId(ref_table[i].type, ref_table[i].id, ref_table[i].name); |
+ } |
+ |
// Debug addresses |
Add(Debug_Address(Debug::k_after_break_target_address).address(), |
DEBUG_ADDRESS, |
@@ -515,16 +568,33 @@ ExternalReferenceTable::ExternalReferenceTable() : refs_(64) { |
} |
// Stat counters |
+ struct StatsRefTableEntry { |
+ StatsCounter* counter; |
+ uint16_t id; |
+ const char* name; |
+ }; |
+ |
+ static const StatsRefTableEntry stats_ref_table[] = { |
+ |
#define COUNTER_ENTRY(name, caption) \ |
- Add(reinterpret_cast<Address>(GetInternalPointer(&Counters::name)), \ |
- STATS_COUNTER, \ |
- Counters::k_##name, \ |
- "Counters::" #name); |
+ { &Counters::name, \ |
+ Counters::k_##name, \ |
+ "Counters::" #name }, |
STATS_COUNTER_LIST_1(COUNTER_ENTRY) |
STATS_COUNTER_LIST_2(COUNTER_ENTRY) |
#undef COUNTER_ENTRY |
+ }; // end of stats_ref_table[]. |
+ |
+ for (size_t i = 0; i < ARRAY_SIZE(stats_ref_table); ++i) { |
+ Add(reinterpret_cast<Address>( |
+ GetInternalPointer(stats_ref_table[i].counter)), |
+ STATS_COUNTER, |
+ stats_ref_table[i].id, |
+ stats_ref_table[i].name); |
+ } |
+ |
// Top addresses |
const char* top_address_format = "Top::get_address_from_id(%i)"; |
size_t top_format_length = strlen(top_address_format); |