[V8] Optimize Integer::New() by caching persistent handles for small integers
authorharaken@chromium.org <haraken@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Jun 2012 08:51:58 +0000 (08:51 +0000)
committerharaken@chromium.org <haraken@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Jun 2012 08:51:58 +0000 (08:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=90043

Reviewed by Adam Barth.

The patch improves performance of Dromaeo/dom-query.html by 3.6%,
and Bindings/scroll-top.html by 17.3%.

The performance results in my Chromium/Linux:

[Dromaeo/dom-query.html]
796310.4 runs/s => 824745.4 runs/s (+3.6%)

[Bindings/scroll-top.html]
204.68 runs/s => 240.15 runs/s (+17.3%)

This patch introduces V8BindingPerIsolateData::IntegerCache (just like
V8BindingPerIsolateData::StringCache) to cache persistent handles
for small integers.

No new tests. No change in behavior.

* bindings/v8/V8Binding.h: Implemented v8Integer() and v8UnsignedInteger(),
which returns cached persistent handles for integers smaller than 64.
(WebCore):
(IntegerCache):
(WebCore::IntegerCache::IntegerCache):
(WebCore::IntegerCache::v8Integer):
(WebCore::IntegerCache::v8UnsignedInteger):
(WebCore::V8BindingPerIsolateData::integerCache):
(V8BindingPerIsolateData):
(WebCore::v8Integer):
(WebCore::v8UnsignedInteger):
* bindings/v8/V8Binding.cpp:
(WebCore):
(WebCore::IntegerCache::createSmallIntegers):
* bindings/v8/WorkerScriptController.cpp:
(~WorkerScriptController): ~V8BindingPerIsolateData() should be called before
isolate->Exit(), since ~V8BindingPerIsolateData() calls V8 APIs that requires
the current isolate.

* bindings/scripts/CodeGeneratorV8.pm: Replaced Integer::New() and Integer::NewFromUnsigned()
with v8Integer() and v8UnsignedInteger().
(GenerateNormalAttrGetter):
(NativeToJSValue):

* bindings/scripts/test/V8/V8TestActiveDOMObject.cpp: Updated run-bindings-tests results.
(WebCore::TestActiveDOMObjectV8Internal::excitingAttrAttrGetter):
* bindings/scripts/test/V8/V8TestObj.cpp: Ditto.
(WebCore::TestObjV8Internal::readOnlyIntAttrAttrGetter):
(WebCore::TestObjV8Internal::shortAttrAttrGetter):
(WebCore::TestObjV8Internal::unsignedShortAttrAttrGetter):
(WebCore::TestObjV8Internal::intAttrAttrGetter):
(WebCore::TestObjV8Internal::reflectedIntegralAttrAttrGetter):
(WebCore::TestObjV8Internal::reflectedUnsignedIntegralAttrAttrGetter):
(WebCore::TestObjV8Internal::reflectedCustomIntegralAttrAttrGetter):
(WebCore::TestObjV8Internal::attrWithGetterExceptionAttrGetter):
(WebCore::TestObjV8Internal::attrWithSetterExceptionAttrGetter):
(WebCore::TestObjV8Internal::withScriptStateAttributeAttrGetter):
(WebCore::TestObjV8Internal::conditionalAttr1AttrGetter):
(WebCore::TestObjV8Internal::conditionalAttr2AttrGetter):
(WebCore::TestObjV8Internal::conditionalAttr3AttrGetter):
(WebCore::TestObjV8Internal::enabledAtRuntimeAttr1AttrGetter):
(WebCore::TestObjV8Internal::enabledAtRuntimeAttr2AttrGetter):
(WebCore::TestObjV8Internal::enabledAtContextAttr1AttrGetter):
(WebCore::TestObjV8Internal::enabledAtContextAttr2AttrGetter):
(WebCore::TestObjV8Internal::strawberryAttrGetter):
(WebCore::TestObjV8Internal::descriptionAttrGetter):
(WebCore::TestObjV8Internal::idAttrGetter):
(WebCore::TestObjV8Internal::intMethodCallback):
(WebCore::TestObjV8Internal::intMethodWithArgsCallback):
(WebCore::TestObjV8Internal::classMethodWithOptionalCallback):
* bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.cpp: Ditto.
(WebCore::TestSerializedScriptValueInterfaceV8Internal::portsAttrGetter):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121421 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/bindings/scripts/CodeGeneratorV8.pm
Source/WebCore/bindings/scripts/test/V8/V8TestActiveDOMObject.cpp
Source/WebCore/bindings/scripts/test/V8/V8TestObj.cpp
Source/WebCore/bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.cpp
Source/WebCore/bindings/v8/V8Binding.cpp
Source/WebCore/bindings/v8/V8Binding.h
Source/WebCore/bindings/v8/WorkerScriptController.cpp

index c74a474..7b39d85 100644 (file)
@@ -1,3 +1,80 @@
+2012-06-28  Kentaro Hara  <haraken@chromium.org>
+
+        [V8] Optimize Integer::New() by caching persistent handles for small integers
+        https://bugs.webkit.org/show_bug.cgi?id=90043
+
+        Reviewed by Adam Barth.
+
+        The patch improves performance of Dromaeo/dom-query.html by 3.6%,
+        and Bindings/scroll-top.html by 17.3%.
+
+        The performance results in my Chromium/Linux:
+
+        [Dromaeo/dom-query.html]
+        796310.4 runs/s => 824745.4 runs/s (+3.6%)
+
+        [Bindings/scroll-top.html]
+        204.68 runs/s => 240.15 runs/s (+17.3%)
+
+        This patch introduces V8BindingPerIsolateData::IntegerCache (just like
+        V8BindingPerIsolateData::StringCache) to cache persistent handles
+        for small integers.
+
+        No new tests. No change in behavior.
+
+        * bindings/v8/V8Binding.h: Implemented v8Integer() and v8UnsignedInteger(),
+        which returns cached persistent handles for integers smaller than 64.
+        (WebCore):
+        (IntegerCache):
+        (WebCore::IntegerCache::IntegerCache):
+        (WebCore::IntegerCache::v8Integer):
+        (WebCore::IntegerCache::v8UnsignedInteger):
+        (WebCore::V8BindingPerIsolateData::integerCache):
+        (V8BindingPerIsolateData):
+        (WebCore::v8Integer):
+        (WebCore::v8UnsignedInteger):
+        * bindings/v8/V8Binding.cpp:
+        (WebCore):
+        (WebCore::IntegerCache::createSmallIntegers):
+        * bindings/v8/WorkerScriptController.cpp:
+        (~WorkerScriptController): ~V8BindingPerIsolateData() should be called before
+        isolate->Exit(), since ~V8BindingPerIsolateData() calls V8 APIs that requires
+        the current isolate.
+
+        * bindings/scripts/CodeGeneratorV8.pm: Replaced Integer::New() and Integer::NewFromUnsigned()
+        with v8Integer() and v8UnsignedInteger().
+        (GenerateNormalAttrGetter):
+        (NativeToJSValue):
+
+        * bindings/scripts/test/V8/V8TestActiveDOMObject.cpp: Updated run-bindings-tests results.
+        (WebCore::TestActiveDOMObjectV8Internal::excitingAttrAttrGetter):
+        * bindings/scripts/test/V8/V8TestObj.cpp: Ditto.
+        (WebCore::TestObjV8Internal::readOnlyIntAttrAttrGetter):
+        (WebCore::TestObjV8Internal::shortAttrAttrGetter):
+        (WebCore::TestObjV8Internal::unsignedShortAttrAttrGetter):
+        (WebCore::TestObjV8Internal::intAttrAttrGetter):
+        (WebCore::TestObjV8Internal::reflectedIntegralAttrAttrGetter):
+        (WebCore::TestObjV8Internal::reflectedUnsignedIntegralAttrAttrGetter):
+        (WebCore::TestObjV8Internal::reflectedCustomIntegralAttrAttrGetter):
+        (WebCore::TestObjV8Internal::attrWithGetterExceptionAttrGetter):
+        (WebCore::TestObjV8Internal::attrWithSetterExceptionAttrGetter):
+        (WebCore::TestObjV8Internal::withScriptStateAttributeAttrGetter):
+        (WebCore::TestObjV8Internal::conditionalAttr1AttrGetter):
+        (WebCore::TestObjV8Internal::conditionalAttr2AttrGetter):
+        (WebCore::TestObjV8Internal::conditionalAttr3AttrGetter):
+        (WebCore::TestObjV8Internal::enabledAtRuntimeAttr1AttrGetter):
+        (WebCore::TestObjV8Internal::enabledAtRuntimeAttr2AttrGetter):
+        (WebCore::TestObjV8Internal::enabledAtContextAttr1AttrGetter):
+        (WebCore::TestObjV8Internal::enabledAtContextAttr2AttrGetter):
+        (WebCore::TestObjV8Internal::strawberryAttrGetter):
+        (WebCore::TestObjV8Internal::descriptionAttrGetter):
+        (WebCore::TestObjV8Internal::idAttrGetter):
+        (WebCore::TestObjV8Internal::intMethodCallback):
+        (WebCore::TestObjV8Internal::intMethodWithArgsCallback):
+        (WebCore::TestObjV8Internal::classMethodWithOptionalCallback):
+        * bindings/scripts/test/V8/V8TestSerializedScriptValueInterface.cpp: Ditto.
+        (WebCore::TestSerializedScriptValueInterfaceV8Internal::portsAttrGetter):
+
 2012-06-28  Kent Tamura  <tkent@chromium.org>
 
         Classify form control states by their owner forms
index 254ec93..b36da40 100644 (file)
@@ -1060,7 +1060,7 @@ END
     MessagePortArray portsCopy(*ports);
     v8::Local<v8::Array> portArray = v8::Array::New(portsCopy.size());
     for (size_t i = 0; i < portsCopy.size(); ++i)
-        portArray->Set(v8::Integer::New(i), toV8(portsCopy[i].get(), info.GetIsolate()));
+        portArray->Set(v8Integer(i, info.GetIsolate()), toV8(portsCopy[i].get(), info.GetIsolate()));
     return portArray;
 END
     } else {
@@ -3892,14 +3892,14 @@ sub NativeToJSValue
     # should be returned instead.
     if ($signature->extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) {
         $value =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g;
-        return "v8::Integer::NewFromUnsigned(std::max(0, " . $value . "))";
+        return "v8UnsignedInteger(std::max(0, " . $value . ")$getIsolateArg)";
     }
 
     # For all the types where we use 'int' as the representation type,
-    # we use Integer::New which has a fast Smi conversion check.
+    # we use v8Integer() which has a fast small integer conversion check.
     my $nativeType = GetNativeType($type);
-    return "v8::Integer::New($value)" if $nativeType eq "int";
-    return "v8::Integer::NewFromUnsigned($value)" if $nativeType eq "unsigned";
+    return "v8Integer($value$getIsolateArg)" if $nativeType eq "int";
+    return "v8UnsignedInteger($value$getIsolateArg)" if $nativeType eq "unsigned";
 
     return "v8DateOrNull($value$getIsolateArg)" if $type eq "Date";
     # long long and unsigned long long are not representable in ECMAScript.
index 37817d5..0a9b88a 100644 (file)
@@ -45,7 +45,7 @@ static v8::Handle<v8::Value> excitingAttrAttrGetter(v8::Local<v8::String> name,
 {
     INC_STATS("DOM.TestActiveDOMObject.excitingAttr._get");
     TestActiveDOMObject* imp = V8TestActiveDOMObject::toNative(info.Holder());
-    return v8::Integer::New(imp->excitingAttr());
+    return v8Integer(imp->excitingAttr(), info.GetIsolate());
 }
 
 static v8::Handle<v8::Value> excitingFunctionCallback(const v8::Arguments& args)
index 40b8d9d..372eadf 100644 (file)
@@ -86,7 +86,7 @@ static v8::Handle<v8::Value> readOnlyIntAttrAttrGetter(v8::Local<v8::String> nam
 {
     INC_STATS("DOM.TestObj.readOnlyIntAttr._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->readOnlyIntAttr());
+    return v8Integer(imp->readOnlyIntAttr(), info.GetIsolate());
 }
 
 static v8::Handle<v8::Value> readOnlyStringAttrAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
@@ -114,7 +114,7 @@ static v8::Handle<v8::Value> shortAttrAttrGetter(v8::Local<v8::String> name, con
 {
     INC_STATS("DOM.TestObj.shortAttr._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->shortAttr());
+    return v8Integer(imp->shortAttr(), info.GetIsolate());
 }
 
 static void shortAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -130,7 +130,7 @@ static v8::Handle<v8::Value> unsignedShortAttrAttrGetter(v8::Local<v8::String> n
 {
     INC_STATS("DOM.TestObj.unsignedShortAttr._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->unsignedShortAttr());
+    return v8Integer(imp->unsignedShortAttr(), info.GetIsolate());
 }
 
 static void unsignedShortAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -146,7 +146,7 @@ static v8::Handle<v8::Value> intAttrAttrGetter(v8::Local<v8::String> name, const
 {
     INC_STATS("DOM.TestObj.intAttr._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->intAttr());
+    return v8Integer(imp->intAttr(), info.GetIsolate());
 }
 
 static void intAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -274,7 +274,7 @@ static v8::Handle<v8::Value> reflectedIntegralAttrAttrGetter(v8::Local<v8::Strin
 {
     INC_STATS("DOM.TestObj.reflectedIntegralAttr._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->getIntegralAttribute(WebCore::HTMLNames::reflectedintegralattrAttr));
+    return v8Integer(imp->getIntegralAttribute(WebCore::HTMLNames::reflectedintegralattrAttr), info.GetIsolate());
 }
 
 static void reflectedIntegralAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -290,7 +290,7 @@ static v8::Handle<v8::Value> reflectedUnsignedIntegralAttrAttrGetter(v8::Local<v
 {
     INC_STATS("DOM.TestObj.reflectedUnsignedIntegralAttr._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::NewFromUnsigned(std::max(0, imp->getIntegralAttribute(WebCore::HTMLNames::reflectedunsignedintegralattrAttr)));
+    return v8UnsignedInteger(std::max(0, imp->getIntegralAttribute(WebCore::HTMLNames::reflectedunsignedintegralattrAttr)), info.GetIsolate());
 }
 
 static void reflectedUnsignedIntegralAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -354,7 +354,7 @@ static v8::Handle<v8::Value> reflectedCustomIntegralAttrAttrGetter(v8::Local<v8:
 {
     INC_STATS("DOM.TestObj.reflectedCustomIntegralAttr._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->getIntegralAttribute(WebCore::HTMLNames::customContentIntegralAttrAttr));
+    return v8Integer(imp->getIntegralAttribute(WebCore::HTMLNames::customContentIntegralAttrAttr), info.GetIsolate());
 }
 
 static void reflectedCustomIntegralAttrAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -406,7 +406,7 @@ static v8::Handle<v8::Value> attrWithGetterExceptionAttrGetter(v8::Local<v8::Str
     int v = imp->attrWithGetterException(ec);
     if (UNLIKELY(ec))
         return V8Proxy::setDOMException(ec, info.GetIsolate());
-    return v8::Integer::New(v);
+    return v8Integer(v, info.GetIsolate());
 }
 
 static void attrWithGetterExceptionAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -425,7 +425,7 @@ static v8::Handle<v8::Value> attrWithSetterExceptionAttrGetter(v8::Local<v8::Str
 {
     INC_STATS("DOM.TestObj.attrWithSetterException._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->attrWithSetterException());
+    return v8Integer(imp->attrWithSetterException(), info.GetIsolate());
 }
 
 static void attrWithSetterExceptionAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -489,7 +489,7 @@ static v8::Handle<v8::Value> withScriptStateAttributeAttrGetter(v8::Local<v8::St
     ScriptState* state = ScriptState::current();
     if (!state)
         return v8::Undefined();
-    return v8::Integer::New(imp->withScriptStateAttribute(state));
+    return v8Integer(imp->withScriptStateAttribute(state), info.GetIsolate());
 }
 
 static void withScriptStateAttributeAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -717,7 +717,7 @@ static v8::Handle<v8::Value> conditionalAttr1AttrGetter(v8::Local<v8::String> na
 {
     INC_STATS("DOM.TestObj.conditionalAttr1._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->conditionalAttr1());
+    return v8Integer(imp->conditionalAttr1(), info.GetIsolate());
 }
 
 #endif // ENABLE(Condition1)
@@ -741,7 +741,7 @@ static v8::Handle<v8::Value> conditionalAttr2AttrGetter(v8::Local<v8::String> na
 {
     INC_STATS("DOM.TestObj.conditionalAttr2._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->conditionalAttr2());
+    return v8Integer(imp->conditionalAttr2(), info.GetIsolate());
 }
 
 #endif // ENABLE(Condition1) && ENABLE(Condition2)
@@ -765,7 +765,7 @@ static v8::Handle<v8::Value> conditionalAttr3AttrGetter(v8::Local<v8::String> na
 {
     INC_STATS("DOM.TestObj.conditionalAttr3._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->conditionalAttr3());
+    return v8Integer(imp->conditionalAttr3(), info.GetIsolate());
 }
 
 #endif // ENABLE(Condition1) || ENABLE(Condition2)
@@ -815,7 +815,7 @@ static v8::Handle<v8::Value> enabledAtRuntimeAttr1AttrGetter(v8::Local<v8::Strin
 {
     INC_STATS("DOM.TestObj.enabledAtRuntimeAttr1._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->enabledAtRuntimeAttr1());
+    return v8Integer(imp->enabledAtRuntimeAttr1(), info.GetIsolate());
 }
 
 static void enabledAtRuntimeAttr1AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -831,7 +831,7 @@ static v8::Handle<v8::Value> enabledAtRuntimeAttr2AttrGetter(v8::Local<v8::Strin
 {
     INC_STATS("DOM.TestObj.enabledAtRuntimeAttr2._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->enabledAtRuntimeAttr2());
+    return v8Integer(imp->enabledAtRuntimeAttr2(), info.GetIsolate());
 }
 
 static void enabledAtRuntimeAttr2AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -847,7 +847,7 @@ static v8::Handle<v8::Value> enabledAtContextAttr1AttrGetter(v8::Local<v8::Strin
 {
     INC_STATS("DOM.TestObj.enabledAtContextAttr1._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->enabledAtContextAttr1());
+    return v8Integer(imp->enabledAtContextAttr1(), info.GetIsolate());
 }
 
 static void enabledAtContextAttr1AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -863,7 +863,7 @@ static v8::Handle<v8::Value> enabledAtContextAttr2AttrGetter(v8::Local<v8::Strin
 {
     INC_STATS("DOM.TestObj.enabledAtContextAttr2._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->enabledAtContextAttr2());
+    return v8Integer(imp->enabledAtContextAttr2(), info.GetIsolate());
 }
 
 static void enabledAtContextAttr2AttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -953,7 +953,7 @@ static v8::Handle<v8::Value> strawberryAttrGetter(v8::Local<v8::String> name, co
 {
     INC_STATS("DOM.TestObj.strawberry._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->blueberry());
+    return v8Integer(imp->blueberry(), info.GetIsolate());
 }
 
 static void strawberryAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -985,14 +985,14 @@ static v8::Handle<v8::Value> descriptionAttrGetter(v8::Local<v8::String> name, c
 {
     INC_STATS("DOM.TestObj.description._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->description());
+    return v8Integer(imp->description(), info.GetIsolate());
 }
 
 static v8::Handle<v8::Value> idAttrGetter(v8::Local<v8::String> name, const v8::AccessorInfo& info)
 {
     INC_STATS("DOM.TestObj.id._get");
     TestObj* imp = V8TestObj::toNative(info.Holder());
-    return v8::Integer::New(imp->id());
+    return v8Integer(imp->id(), info.GetIsolate());
 }
 
 static void idAttrSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
@@ -1044,7 +1044,7 @@ static v8::Handle<v8::Value> intMethodCallback(const v8::Arguments& args)
 {
     INC_STATS("DOM.TestObj.intMethod");
     TestObj* imp = V8TestObj::toNative(args.Holder());
-    return v8::Integer::New(imp->intMethod());
+    return v8Integer(imp->intMethod(), args.GetIsolate());
 }
 
 static v8::Handle<v8::Value> intMethodWithArgsCallback(const v8::Arguments& args)
@@ -1056,7 +1056,7 @@ static v8::Handle<v8::Value> intMethodWithArgsCallback(const v8::Arguments& args
     EXCEPTION_BLOCK(int, intArg, toInt32(MAYBE_MISSING_PARAMETER(args, 0, DefaultIsUndefined)));
     STRING_TO_V8PARAMETER_EXCEPTION_BLOCK(V8Parameter<>, strArg, MAYBE_MISSING_PARAMETER(args, 1, DefaultIsUndefined));
     EXCEPTION_BLOCK(TestObj*, objArg, V8TestObj::HasInstance(MAYBE_MISSING_PARAMETER(args, 2, DefaultIsUndefined)) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(MAYBE_MISSING_PARAMETER(args, 2, DefaultIsUndefined))) : 0);
-    return v8::Integer::New(imp->intMethodWithArgs(intArg, strArg, objArg));
+    return v8Integer(imp->intMethodWithArgs(intArg, strArg, objArg), args.GetIsolate());
 }
 
 static v8::Handle<v8::Value> objMethodCallback(const v8::Arguments& args)
@@ -1603,10 +1603,10 @@ static v8::Handle<v8::Value> classMethodWithOptionalCallback(const v8::Arguments
 {
     INC_STATS("DOM.TestObj.classMethodWithOptional");
     if (args.Length() <= 0) {
-        return v8::Integer::New(TestObj::classMethodWithOptional());
+        return v8Integer(TestObj::classMethodWithOptional(), args.GetIsolate());
     }
     EXCEPTION_BLOCK(int, arg, toInt32(MAYBE_MISSING_PARAMETER(args, 0, DefaultIsUndefined)));
-    return v8::Integer::New(TestObj::classMethodWithOptional(arg));
+    return v8Integer(TestObj::classMethodWithOptional(arg), args.GetIsolate());
 }
 
 #if ENABLE(Condition1)
index 28ecd94..3b0f2f6 100644 (file)
@@ -103,7 +103,7 @@ static v8::Handle<v8::Value> portsAttrGetter(v8::Local<v8::String> name, const v
     MessagePortArray portsCopy(*ports);
     v8::Local<v8::Array> portArray = v8::Array::New(portsCopy.size());
     for (size_t i = 0; i < portsCopy.size(); ++i)
-        portArray->Set(v8::Integer::New(i), toV8(portsCopy[i].get(), info.GetIsolate()));
+        portArray->Set(v8Integer(i, info.GetIsolate()), toV8(portsCopy[i].get(), info.GetIsolate()));
     return portArray;
 }
 
index 6990186..d8836c7 100644 (file)
@@ -490,7 +490,27 @@ v8::Local<v8::String> StringCache::v8ExternalStringSlow(StringImpl* stringImpl,
 
     return newString;
 }
-    
+
+void IntegerCache::createSmallIntegers()
+{
+    ASSERT(!m_initialized);
+    // We initialize m_smallIntegers not in a constructor but in v8Integer(),
+    // because Integer::New() requires a HandleScope. At the point where
+    // IntegerCache is constructed, a HandleScope might not exist.
+    for (int value = 0; value < numberOfCachedSmallIntegers; value++)
+        m_smallIntegers[value] = v8::Persistent<v8::Integer>::New(v8::Integer::New(value));
+    m_initialized = true;
+}
+
+IntegerCache::~IntegerCache()
+{
+    if (m_initialized) {
+        for (int value = 0; value < numberOfCachedSmallIntegers; value++)
+            m_smallIntegers[value].Dispose();
+        m_initialized = false;
+    }
+}
+
 v8::Persistent<v8::FunctionTemplate> createRawTemplate()
 {
     v8::HandleScope scope;
index 9e9c5bb..5d0dbe2 100644 (file)
@@ -89,6 +89,38 @@ namespace WebCore {
         RefPtr<StringImpl> m_lastStringImpl;
     };
 
+    const int numberOfCachedSmallIntegers = 64;
+
+    class IntegerCache {
+    public:
+        IntegerCache() : m_initialized(false) { };
+        ~IntegerCache();
+
+        v8::Handle<v8::Integer> v8Integer(int value)
+        {
+            if (!m_initialized)
+                createSmallIntegers();
+            if (0 <= value && value < numberOfCachedSmallIntegers)
+                return m_smallIntegers[value];
+            return v8::Integer::New(value);
+        }
+
+        v8::Handle<v8::Integer> v8UnsignedInteger(unsigned value)
+        {
+            if (!m_initialized)
+                createSmallIntegers();
+            if (value < static_cast<unsigned>(numberOfCachedSmallIntegers))
+                return m_smallIntegers[value];
+            return v8::Integer::NewFromUnsigned(value);
+        }
+
+    private:
+        void createSmallIntegers();
+
+        v8::Persistent<v8::Integer> m_smallIntegers[numberOfCachedSmallIntegers];
+        bool m_initialized;
+    };
+
     class ScriptGCEventListener;
 
     class GCEventData {
@@ -142,6 +174,8 @@ namespace WebCore {
         }
 
         StringCache* stringCache() { return &m_stringCache; }
+        IntegerCache* integerCache() { return &m_integerCache; }
+
 #if ENABLE(INSPECTOR)
         void visitExternalStrings(ExternalStringVisitor*);
 #endif
@@ -190,6 +224,7 @@ namespace WebCore {
         v8::Persistent<v8::FunctionTemplate> m_toStringTemplate;
         v8::Persistent<v8::FunctionTemplate> m_lazyEventListenerToStringTemplate;
         StringCache m_stringCache;
+        IntegerCache m_integerCache;
 
         DOMDataList m_domDataList;
         DOMDataStore* m_domDataStore;
@@ -290,6 +325,18 @@ namespace WebCore {
         return v8ExternalString(string, isolate);
     }
 
+    inline v8::Handle<v8::Integer> v8Integer(int value, v8::Isolate* isolate = 0)
+    {
+        V8BindingPerIsolateData* data = V8BindingPerIsolateData::current(isolate);
+        return data->integerCache()->v8Integer(value);
+    }
+
+    inline v8::Handle<v8::Integer> v8UnsignedInteger(unsigned value, v8::Isolate* isolate = 0)
+    {
+        V8BindingPerIsolateData* data = V8BindingPerIsolateData::current(isolate);
+        return data->integerCache()->v8UnsignedInteger(value);
+    }
+
     template<typename T>
     v8::Handle<v8::Value> v8Array(const Vector<T>& iterator, v8::Isolate* isolate)
     {
index cf19e0e..79c8810 100644 (file)
@@ -77,8 +77,8 @@ WorkerScriptController::~WorkerScriptController()
     WebKit::Platform::current()->didStopWorkerRunLoop(WebKit::WebWorkerRunLoop(&m_workerContext->thread()->runLoop()));
 #endif
     m_proxy.clear();
-    m_isolate->Exit();
     V8BindingPerIsolateData::dispose(m_isolate);
+    m_isolate->Exit();
     m_isolate->Dispose();
 }