From 286ea1d88a41a670a17bd82d85a553c2df53c0c8 Mon Sep 17 00:00:00 2001 From: Bruce Dawson Date: Mon, 5 Jan 2015 14:11:00 -0800 Subject: Remove run-time calculation of hash constants in pdfium. PDFium static initializers must go. Static initializers are prohibited by the style guide. They have negative consequences including increased startup time (from pulling in additional code pages) and reduced sharing of data pages (since the variables can't go in the read-only data segment). This change uses a template struct and typed enums to reproduce JS_CalcHash at run-time. An unsigned long long constant and masking with 0xFFFFFFFF are used to avoid compile errors due to integer overflow of compile-time constants. The HashVerify class is used to check the results, necessary since none of the functions in global.cpp are called when pdfium_test.exe runs. const_expr would be a much cleaner way to implement this change but it is not yet widely supported. On the Windows release build this reduces the code size (.text virtual size) by 0x240 (576) bytes, the .data section by 0x20 bytes (for eight unsigned globals), and the .rdata section by 0x20 bytes (the unneeded string savings, minus the eight unsigned globals now being there). BUG=441899 R=tsepez@chromium.org Review URL: https://codereview.chromium.org/792043005 --- fpdfsdk/src/javascript/global.cpp | 74 ++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/fpdfsdk/src/javascript/global.cpp b/fpdfsdk/src/javascript/global.cpp index 04f9ef9da3..88b3fe77ce 100644 --- a/fpdfsdk/src/javascript/global.cpp +++ b/fpdfsdk/src/javascript/global.cpp @@ -16,14 +16,72 @@ /* ---------------------------- global ---------------------------- */ -extern const unsigned int JSCONST_nStringHash = JS_CalcHash(VALUE_NAME_STRING,wcslen(VALUE_NAME_STRING)); -extern const unsigned int JSCONST_nNumberHash = JS_CalcHash(VALUE_NAME_NUMBER,wcslen(VALUE_NAME_NUMBER)); -extern const unsigned int JSCONST_nBoolHash = JS_CalcHash(VALUE_NAME_BOOLEAN,wcslen(VALUE_NAME_BOOLEAN)); -extern const unsigned int JSCONST_nDateHash = JS_CalcHash(VALUE_NAME_DATE,wcslen(VALUE_NAME_DATE)); -extern const unsigned int JSCONST_nObjectHash = JS_CalcHash(VALUE_NAME_OBJECT,wcslen(VALUE_NAME_OBJECT)); -extern const unsigned int JSCONST_nFXobjHash = JS_CalcHash(VALUE_NAME_FXOBJ,wcslen(VALUE_NAME_FXOBJ)); -extern const unsigned int JSCONST_nNullHash = JS_CalcHash(VALUE_NAME_NULL,wcslen(VALUE_NAME_NULL)); -extern const unsigned int JSCONST_nUndefHash = JS_CalcHash(VALUE_NAME_UNDEFINED,wcslen(VALUE_NAME_UNDEFINED)); +// Helper class for compile-time calculation of hash values in order to +// avoid having global object initializers. +template +struct CHash; + +// Only needed to hash single-character strings. +template +struct CHash { + static const unsigned value = N; +}; + +template +struct CHash { + static const unsigned value = (ACC * 1313LLU + N) & 0xFFFFFFFF; +}; + +template +struct CHash { + static const unsigned value = CHash::value, Ns...>::value; +}; + +extern const unsigned int JSCONST_nStringHash = + CHash<'s','t','r','i','n','g'>::value; +extern const unsigned int JSCONST_nNumberHash = + CHash<'n','u','m','b','e','r'>::value; +extern const unsigned int JSCONST_nBoolHash = + CHash<'b','o','o','l','e','a','n'>::value; +extern const unsigned int JSCONST_nDateHash = + CHash<'d','a','t','e'>::value; +extern const unsigned int JSCONST_nObjectHash = + CHash<'o','b','j','e','c','t'>::value; +extern const unsigned int JSCONST_nFXobjHash = + CHash<'f','x','o','b','j'>::value; +extern const unsigned int JSCONST_nNullHash = + CHash<'n','u','l','l'>::value; +extern const unsigned int JSCONST_nUndefHash = + CHash<'u','n','d','e','f','i','n','e','d'>::value; + +#ifdef _DEBUG +class HashVerify +{ +public: + HashVerify(); +} g_hashVerify; + +HashVerify::HashVerify() +{ + ASSERT(JSCONST_nStringHash == + JS_CalcHash(VALUE_NAME_STRING,wcslen(VALUE_NAME_STRING))); + ASSERT(JSCONST_nNumberHash == + JS_CalcHash(VALUE_NAME_NUMBER,wcslen(VALUE_NAME_NUMBER))); + ASSERT(JSCONST_nBoolHash == + JS_CalcHash(VALUE_NAME_BOOLEAN,wcslen(VALUE_NAME_BOOLEAN))); + ASSERT(JSCONST_nDateHash == + JS_CalcHash(VALUE_NAME_DATE,wcslen(VALUE_NAME_DATE))); + ASSERT(JSCONST_nObjectHash == + JS_CalcHash(VALUE_NAME_OBJECT,wcslen(VALUE_NAME_OBJECT))); + ASSERT(JSCONST_nFXobjHash == + JS_CalcHash(VALUE_NAME_FXOBJ,wcslen(VALUE_NAME_FXOBJ))); + ASSERT(JSCONST_nNullHash == + JS_CalcHash(VALUE_NAME_NULL,wcslen(VALUE_NAME_NULL))); + ASSERT(JSCONST_nUndefHash == + JS_CalcHash(VALUE_NAME_UNDEFINED,wcslen(VALUE_NAME_UNDEFINED))); +} +#endif + BEGIN_JS_STATIC_CONST(CJS_Global) END_JS_STATIC_CONST() -- cgit v1.2.3