Commit 7d5999fb authored by jl@opera.com's avatar jl@opera.com

Optimize named property access on CSSStyleDeclaration objects

When reading property on a CSSStyleDeclaration object, the property name
is transformed into a possible CSS property name and looked up as such.
This transformation involves copying the property name to a StringBuilder
while converting from camelCase to dash-separated.

Positive matches are cached in a local static hash map, but negative
matches were not.  A script reading properties like "getPropertyValue"
would trigger the conversion to "get-property-value" and CSS property
lookup every time.

Optimize by caching negative matches as well as positive ones.

BUG=

Review URL: https://codereview.chromium.org/219153002

git-svn-id: svn://svn.chromium.org/blink/trunk@170490 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 3d8965a9
<!DOCTYPE html>
<html>
<head>
<script src="../resources/runner.js"></script>
</head>
<body>
<div id="test"></div>
</body>
<script>
var div = document.getElementById("test");
var properties = {
'azimuth' : 'right',
'background-color' : 'green',
'background-image' : 'url(\'test.png\')',
'background-position' : 'top',
'background-repeat' : 'repeat-x',
'background' : '#ffffff url(\'img_tree.png\') no-repeat right top',
'border' : '20px dotted red',
'border-bottom-style' : 'dotted',
'border-collapse' : 'separate',
'border-color' : 'blue',
'border-spacing' : '3px',
'border-style' : 'solid',
'border-top' : 'green',
'border-width' : '20em',
'bottom' : '20%',
'caption-side' : 'top',
'clear' : 'both',
'clip' : 'rect(5px, 40px, 45px, 5px)',
'color' : 'red',
'content' : 'normal',
'direction' : 'rtl',
'display' : 'block',
'css-float' : 'right',
'font-family' : '"Times New Roman",Georgia,Serif',
'font-size' : '13px',
'font-variant' : 'small-caps',
'font-weight' : '700',
'font' : 'italic bold 12px/30px Georgia, serif',
'height' : '200px',
'left' : '20%',
'letter-spacing' : '10px',
'line-height' : '40px',
'list-style-image' : 'url(\'test.png\')',
'list-style-position' : 'outside',
'list-style-type' : 'decimal',
'list-style' : 'circle inside',
'margin-right' : '50px',
'margin' : '10px 20px 30px 5em',
'max-height' : '700px',
'max-width' : '300px',
'min-height' : '100px',
'min-width' : '100px',
'outline-color' : 'gray',
'outline-style' : 'dotted',
'outline-width' : '5px',
'padding-top' : '30px',
'padding' : '30px 20px 10px 50px',
'page-break-after' : 'always',
'page-break-inside' : 'auto',
'pause' : '2s',
'position' : 'static',
'right' : '150px',
'text-align' : 'center',
'text-decoration' : 'blink',
'text-transform' : 'capitalize',
'top' : '25%',
'vertical-align' : 'text-bottom',
'visibility' : 'visible',
'width' : '300px',
'webkit-transform' : 'scale3d(0.5, 0.5, 0.5)',
'word-spacing' : '40px',
};
PerfTestRunner.measureRunsPerSecond({run:function() {
for (key in properties) {
var value = div.style.getPropertyValue(key);
div.style.removeProperty(key);
div.style.setProperty(key, properties[key]);
}
}});
</script>
</html>
...@@ -84,6 +84,50 @@ struct CSSPropertyInfo { ...@@ -84,6 +84,50 @@ struct CSSPropertyInfo {
CSSPropertyID propID; CSSPropertyID propID;
}; };
static CSSPropertyID cssResolvedPropertyID(const String& propertyName)
{
unsigned length = propertyName.length();
if (!length)
return CSSPropertyInvalid;
StringBuilder builder;
builder.reserveCapacity(length);
unsigned i = 0;
bool hasSeenDash = false;
if (hasCSSPropertyNamePrefix(propertyName, "css"))
i += 3;
else if (hasCSSPropertyNamePrefix(propertyName, "webkit"))
builder.append('-');
else if (isASCIIUpper(propertyName[0]))
return CSSPropertyInvalid;
bool hasSeenUpper = isASCIIUpper(propertyName[i]);
builder.append(toASCIILower(propertyName[i++]));
for (; i < length; ++i) {
UChar c = propertyName[i];
if (!isASCIIUpper(c)) {
if (c == '-')
hasSeenDash = true;
builder.append(c);
} else {
hasSeenUpper = true;
builder.append('-');
builder.append(toASCIILower(c));
}
}
// Reject names containing both dashes and upper-case characters, such as "border-rightColor".
if (hasSeenDash && hasSeenUpper)
return CSSPropertyInvalid;
String propName = builder.toString();
return cssPropertyID(propName);
}
// When getting properties on CSSStyleDeclarations, the name used from // When getting properties on CSSStyleDeclarations, the name used from
// Javascript and the actual name of the property are not the same, so // Javascript and the actual name of the property are not the same, so
// we have to do the following translation. The translation turns upper // we have to do the following translation. The translation turns upper
...@@ -100,54 +144,13 @@ static CSSPropertyInfo* cssPropertyInfo(v8::Handle<v8::String> v8PropertyName) ...@@ -100,54 +144,13 @@ static CSSPropertyInfo* cssPropertyInfo(v8::Handle<v8::String> v8PropertyName)
DEFINE_STATIC_LOCAL(CSSPropertyInfoMap, map, ()); DEFINE_STATIC_LOCAL(CSSPropertyInfoMap, map, ());
CSSPropertyInfo* propInfo = map.get(propertyName); CSSPropertyInfo* propInfo = map.get(propertyName);
if (!propInfo) { if (!propInfo) {
unsigned length = propertyName.length(); propInfo = new CSSPropertyInfo();
if (!length) propInfo->propID = cssResolvedPropertyID(propertyName);
return 0; map.add(propertyName, propInfo);
StringBuilder builder;
builder.reserveCapacity(length);
unsigned i = 0;
bool hasSeenDash = false;
if (hasCSSPropertyNamePrefix(propertyName, "css"))
i += 3;
else if (hasCSSPropertyNamePrefix(propertyName, "webkit"))
builder.append('-');
else if (isASCIIUpper(propertyName[0]))
return 0;
bool hasSeenUpper = isASCIIUpper(propertyName[i]);
builder.append(toASCIILower(propertyName[i++]));
for (; i < length; ++i) {
UChar c = propertyName[i];
if (!isASCIIUpper(c)) {
if (c == '-')
hasSeenDash = true;
builder.append(c);
}
else {
hasSeenUpper = true;
builder.append('-');
builder.append(toASCIILower(c));
}
}
// Reject names containing both dashes and upper-case characters, such as "border-rightColor".
if (hasSeenDash && hasSeenUpper)
return 0;
String propName = builder.toString();
CSSPropertyID propertyID = cssPropertyID(propName);
if (propertyID && RuntimeCSSEnabled::isCSSPropertyEnabled(propertyID)) {
propInfo = new CSSPropertyInfo();
propInfo->propID = propertyID;
map.add(propertyName, propInfo);
}
} }
return propInfo; if (propInfo->propID && RuntimeCSSEnabled::isCSSPropertyEnabled(propInfo->propID))
return propInfo;
return 0;
} }
void V8CSSStyleDeclaration::namedPropertyEnumeratorCustom(const v8::PropertyCallbackInfo<v8::Array>& info) void V8CSSStyleDeclaration::namedPropertyEnumeratorCustom(const v8::PropertyCallbackInfo<v8::Array>& info)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment