Author: [email protected]
Date: Tue Jan 27 03:30:44 2009
New Revision: 1173
Modified:
branches/bleeding_edge/src/serialize.cc
Log:
Reduce the size of a release sample shell by 55k.
The ExternalReferenceTable population code was code driven, using the list
macro callbacks to call an Add() function. Additionally this Add()
function was defined in the class defintion, making it inline. This caused
this single function to be ~100k of code. It is now mostly table driven,
but there are still some cases left as code, and these could be improved in
the future for further reduction in binary size.
Review URL: http://codereview.chromium.org/18761
Modified: branches/bleeding_edge/src/serialize.cc
==============================================================================
--- branches/bleeding_edge/src/serialize.cc (original)
+++ branches/bleeding_edge/src/serialize.cc Tue Jan 27 03:30:44 2009
@@ -417,7 +417,8 @@
private:
static ExternalReferenceTable* instance_;
- ExternalReferenceTable();
+ ExternalReferenceTable() : refs_(64) { PopulateTable(); }
+ ~ExternalReferenceTable() { }
struct ExternalReferenceEntry {
Address address;
@@ -425,16 +426,13 @@
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];
@@ -444,28 +442,81 @@
ExternalReferenceTable* ExternalReferenceTable::instance_ = NULL;
-ExternalReferenceTable::ExternalReferenceTable() : refs_(64) {
+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;
+}
+
+
+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,23 +527,26 @@
// 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(),
@@ -515,15 +569,30 @@
}
// 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)";
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---