The Big De-Inlining. 450k code size reduction (32-bit x86.)
authorsnej@chromium.org <snej@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Nov 2009 00:11:22 +0000 (00:11 +0000)
committersnej@chromium.org <snej@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Nov 2009 00:11:22 +0000 (00:11 +0000)
- Various inline functions in V8Binding.h made non-inline.
- Some renaming for consistency.
- New function createRawTemplate().
https://bugs.webkit.org/show_bug.cgi?id=31383

Reviewed by Dimitri Glazkov.

* bindings/scripts/CodeGeneratorV8.pm:
* bindings/v8/V8Binding.cpp:
(WebCore::v8DOMWrapperToNative):
(WebCore::v8ValueToWebCoreString):
(WebCore::v8ValueToAtomicWebCoreString):
(WebCore::toInt32):
(WebCore::toWebCoreString):
(WebCore::toWebCoreStringWithNullCheck):
(WebCore::toAtomicWebCoreStringWithNullCheck):
(WebCore::toWebCoreStringWithNullOrUndefinedCheck):
(WebCore::isUndefinedOrNull):
(WebCore::v8Boolean):
(WebCore::v8UndetectableString):
(WebCore::v8StringOrNull):
(WebCore::v8StringOrUndefined):
(WebCore::v8StringOrFalse):
(WebCore::v8StringToWebCoreString):
(WebCore::v8ExternalString):
(WebCore::createRawTemplate):  New function.
* bindings/v8/V8Binding.h:
(WebCore::v8DOMWrapperTo):
(WebCore::v8DOMWrapperToNode):
(WebCore::v8StringToWebCoreString):
(WebCore::v8StringToAtomicWebCoreString):

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

WebCore/ChangeLog
WebCore/bindings/scripts/CodeGeneratorV8.pm
WebCore/bindings/v8/V8Binding.cpp
WebCore/bindings/v8/V8Binding.h

index 12ad15dcbf1619db45ae061465bc3862646e45ac..2a78fe0341647e96e2915c934a4404781b91b1fc 100644 (file)
@@ -1,3 +1,38 @@
+2009-11-11  Jens Alfke  <snej@chromium.org>
+
+        Reviewed by Dimitri Glazkov.
+
+        The Big De-Inlining. 450k code size reduction (32-bit x86.)
+        - Various inline functions in V8Binding.h made non-inline.
+        - Some renaming for consistency.
+        - New function createRawTemplate().
+        https://bugs.webkit.org/show_bug.cgi?id=31383
+
+        * bindings/scripts/CodeGeneratorV8.pm:
+        * bindings/v8/V8Binding.cpp:
+        (WebCore::v8DOMWrapperToNative):
+        (WebCore::v8ValueToWebCoreString):
+        (WebCore::v8ValueToAtomicWebCoreString):
+        (WebCore::toInt32):
+        (WebCore::toWebCoreString):
+        (WebCore::toWebCoreStringWithNullCheck):
+        (WebCore::toAtomicWebCoreStringWithNullCheck):
+        (WebCore::toWebCoreStringWithNullOrUndefinedCheck):
+        (WebCore::isUndefinedOrNull):
+        (WebCore::v8Boolean):
+        (WebCore::v8UndetectableString):
+        (WebCore::v8StringOrNull):
+        (WebCore::v8StringOrUndefined):
+        (WebCore::v8StringOrFalse):
+        (WebCore::v8StringToWebCoreString):
+        (WebCore::v8ExternalString):
+        (WebCore::createRawTemplate):  New function.
+        * bindings/v8/V8Binding.h:
+        (WebCore::v8DOMWrapperTo):
+        (WebCore::v8DOMWrapperToNode):
+        (WebCore::v8StringToWebCoreString):
+        (WebCore::v8StringToAtomicWebCoreString):
+
 2009-11-11  Jens Alfke  <snej@chromium.org>
 
         Reviewed by Dimitri Glazkov.
index 6bc74f3c1748d179d9111f981e5fd44f0a1f47df..835b3c6aebe8795c9facdd63fb5559d68e2ca9d9 100644 (file)
@@ -350,15 +350,16 @@ sub HolderToNative
     my $dataNode = shift;
     my $implClassName = shift;
     my $classIndex = shift;
+    my $holder = shift || "holder";   # optional param
 
     if (IsNodeSubType($dataNode)) {
         push(@implContentDecls, <<END);
-    $implClassName* imp = V8DOMWrapper::convertDOMWrapperToNode<$implClassName>(holder);
+    $implClassName* imp = v8DOMWrapperToNode<$implClassName>($holder);
 END
 
     } else {
         push(@implContentDecls, <<END);
-    $implClassName* imp = V8DOMWrapper::convertToNativeObject<$implClassName>(V8ClassIndex::$classIndex, holder);
+    $implClassName* imp = v8DOMWrapperTo<$implClassName>(V8ClassIndex::$classIndex, $holder);
 END
 
   }
@@ -397,7 +398,7 @@ sub GenerateDomainSafeFunctionGetter
     }
 END
 
-  HolderToNative($dataNode, $implClassName, $classIndex);
+    HolderToNative($dataNode, $implClassName, $classIndex);
 
     push(@implContentDecls, <<END);
     if (!V8Proxy::canAccessFrame(imp->frame(), false)) {
@@ -428,7 +429,7 @@ END
 
     if ($classIndex eq "DOMWINDOW") {
         push(@implContentDecls, <<END);
-    DOMWindow* window = V8DOMWrapper::convertToNativeObject<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder());
+    DOMWindow* window = v8DOMWrapperTo<DOMWindow>(V8ClassIndex::DOMWINDOW, info.Holder());
     // Get the proxy corresponding to the DOMWindow if possible to
     // make sure that the constructor function is constructed in the
     // context of the DOMWindow and not in the context of the caller.
@@ -437,7 +438,7 @@ END
     } elsif ($classIndex eq "DEDICATEDWORKERCONTEXT" or $classIndex eq "WORKERCONTEXT" or $classIndex eq "SHAREDWORKERCONTEXT") {
         $implIncludes{"WorkerContextExecutionProxy.h"} = 1;
         push(@implContentDecls, <<END);
-    WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder());
+    WorkerContext* workerContext = v8DOMWrapperTo<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder());
     return V8DOMWrapper::getConstructor(type, workerContext);
 END
     } else {
@@ -504,7 +505,7 @@ END
 
     if ($isPodType) {
         push(@implContentDecls, <<END);
-    V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());
+    V8SVGPODTypeWrapper<$implClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());
     $implClassName imp_instance = *imp_wrapper;
 END
         if ($getterStringUsesImp) {
@@ -525,12 +526,12 @@ END
     if (holder.IsEmpty()) return v8::Handle<v8::Value>();
 END
       }
-        HolderToNative($dataNode, $implClassName, $classIndex);
+        HolderToNative($dataNode, $implClassName, $classIndex, "info");
     } else {
         push(@implContentDecls, <<END);
     v8::Handle<v8::Object> holder = info.Holder();
 END
-        HolderToNative($dataNode, $implClassName, $classIndex);
+        HolderToNative($dataNode, $implClassName, $classIndex, "info");
     }
 
     # Generate security checks if necessary
@@ -577,10 +578,6 @@ END
         $getterString = "imp_instance";
     }
 
-    if ($nativeType eq "String") {
-        $getterString = "toString($getterString)";
-    }
-
     my $result;
     my $wrapper;
 
@@ -694,7 +691,7 @@ sub GenerateNormalAttrSetter
     if ($isPodType) {
         $implClassName = GetNativeType($implClassName);
         $implIncludes{"V8SVGPODTypeWrapper.h"} = 1;
-        push(@implContentDecls, "    V8SVGPODTypeWrapper<$implClassName>* wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());\n");
+        push(@implContentDecls, "    V8SVGPODTypeWrapper<$implClassName>* wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$implClassName> >(V8ClassIndex::$classIndex, info.Holder());\n");
         push(@implContentDecls, "    $implClassName imp_instance = *wrapper;\n");
         push(@implContentDecls, "    $implClassName* imp = &imp_instance;\n");
 
@@ -710,12 +707,12 @@ END
     if (holder.IsEmpty()) return;
 END
       }
-        HolderToNative($dataNode, $implClassName, $classIndex);
+        HolderToNative($dataNode, $implClassName, $classIndex, "info");
     } else {
         push(@implContentDecls, <<END);
     v8::Handle<v8::Object> holder = info.Holder();
 END
-        HolderToNative($dataNode, $implClassName, $classIndex);
+        HolderToNative($dataNode, $implClassName, $classIndex, "info");
     }
 
     my $nativeType = GetNativeTypeFromSignature($attribute->signature, 0);
@@ -845,7 +842,7 @@ sub GenerateFunctionCallback
 
     if (IsPodType($implClassName)) {
         my $nativeClassName = GetNativeType($implClassName);
-        push(@implContentDecls, "    V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = V8DOMWrapper::convertToNativeObject<V8SVGPODTypeWrapper<$nativeClassName> >(V8ClassIndex::$classIndex, args.Holder());\n");
+        push(@implContentDecls, "    V8SVGPODTypeWrapper<$nativeClassName>* imp_wrapper = v8DOMWrapperTo<V8SVGPODTypeWrapper<$nativeClassName> >(V8ClassIndex::$classIndex, args.Holder());\n");
         push(@implContentDecls, "    $nativeClassName imp_instance = *imp_wrapper;\n");
         push(@implContentDecls, "    $nativeClassName* imp = &imp_instance;\n");
     } else {
@@ -1401,19 +1398,12 @@ END
 }
 
 v8::Persistent<v8::FunctionTemplate> ${className}::GetRawTemplate() {
-  static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_;
-  if (${className}_raw_cache_.IsEmpty()) {
-    v8::HandleScope scope;
-    v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(V8Proxy::checkNewLegal);
-    ${className}_raw_cache_ = v8::Persistent<v8::FunctionTemplate>::New(result);
-  }
+  static v8::Persistent<v8::FunctionTemplate> ${className}_raw_cache_ = createRawTemplate();
   return ${className}_raw_cache_;
 }
 
 v8::Persistent<v8::FunctionTemplate> ${className}::GetTemplate() {
-  static v8::Persistent<v8::FunctionTemplate> ${className}_cache_;
-  if (${className}_cache_.IsEmpty())
-    ${className}_cache_ = Configure${className}Template(GetRawTemplate());
+  static v8::Persistent<v8::FunctionTemplate> ${className}_cache_ = Configure${className}Template(GetRawTemplate());
   return ${className}_cache_;
 }
 
@@ -1620,7 +1610,7 @@ sub GetTypeFromSignature
     my $signature = shift;
 
     my $type = $codeGenerator->StripModule($signature->type);
-    if (($type eq "DOMString") && $signature->extendedAttributes->{"HintAtomic"}) {
+    if (($type eq "DOMString") && ($signature->extendedAttributes->{"HintAtomic"} || $signature->extendedAttributes->{"Reflect"})) {
         $type = "AtomicString";
     }
 
@@ -1913,14 +1903,19 @@ sub JSValueToNative
     return "static_cast<SVGPaint::SVGPaintType>($value->ToInt32()->Int32Value())" if $type eq "SVGPaintType";
 
     if ($type eq "AtomicString") {
-        return "v8ValueToAtomicWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
+        return "toAtomicWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
         return "v8ValueToAtomicWebCoreString($value)";
     }
 
-    return "toWebCoreString($value)" if $type eq "DOMUserData";
+    if ($type eq "DOMUserData") {
+        return "toWebCoreString(args, $1)" if $value =~ /args\[(\d+)]/;
+        return "toWebCoreString($value)";
+    }
     if ($type eq "DOMString") {
         return "toWebCoreStringWithNullCheck($value)" if $signature->extendedAttributes->{"ConvertNullToNullString"};
         return "toWebCoreStringWithNullOrUndefinedCheck($value)" if $signature->extendedAttributes->{"ConvertUndefinedOrNullToNullString"};
+        
+        return "toWebCoreString(args, $1)" if $value =~ /args\[(\d+)]/;
         return "toWebCoreString($value)";
     }
 
@@ -1947,7 +1942,7 @@ sub JSValueToNative
         $implIncludes{"V8Node.h"} = 1;
 
         # EventTarget is not in DOM hierarchy, but all Nodes are EventTarget.
-        return "V8Node::HasInstance($value) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0";
+        return "V8Node::HasInstance($value) ? v8DOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast($value)) : 0";
     }
 
     if ($type eq "XPathNSResolver") {
@@ -1962,7 +1957,7 @@ sub JSValueToNative
 
         # Perform type checks on the parameter, if it is expected Node type,
         # return NULL.
-        return "V8${type}::HasInstance($value) ? V8DOMWrapper::convertDOMWrapperToNode<${type}>(v8::Handle<v8::Object>::Cast($value)) : 0";
+        return "V8${type}::HasInstance($value) ? v8DOMWrapperToNode<${type}>(v8::Handle<v8::Object>::Cast($value)) : 0";
     } else {
         # TODO: Temporary to avoid Window name conflict.
         my $classIndex = uc($type);
@@ -1981,7 +1976,7 @@ sub JSValueToNative
 
         # Perform type checks on the parameter, if it is expected Node type,
         # return NULL.
-        return "V8${type}::HasInstance($value) ? V8DOMWrapper::convertToNativeObject<${implClassName}>(V8ClassIndex::${classIndex}, v8::Handle<v8::Object>::Cast($value)) : 0";
+        return "V8${type}::HasInstance($value) ? v8DOMWrapperTo<${implClassName}>(V8ClassIndex::${classIndex}, v8::Handle<v8::Object>::Cast($value)) : 0";
     }
 }
 
@@ -2114,8 +2109,8 @@ sub ReturnNativeToJSValue
     my $className= "V8$type";
 
     return "return v8::Date::New(static_cast<double>($value))" if $type eq "DOMTimeStamp";
-    return "return $value ? v8::True() : v8::False()" if $type eq "boolean";
-    return "return v8::Handle<v8::Value>()" if $type eq "void";
+    return "return v8Boolean($value)" if $type eq "boolean";
+    return "return v8::Handle<v8::Value>()" if $type eq "void";     # equivalent to v8::Undefined()
 
     # For all the types where we use 'int' as the representation type,
     # we use Integer::New which has a fast Smi conversion check.
index 9ac7eae049c2d097970bcb55ebaee1c43d7017a0..30e6610514d5f8ca5d98e3777489521d3d27f3d4 100644 (file)
@@ -128,13 +128,122 @@ private:
 #endif
 };
 
-enum ExternalMode {
-    Externalize,
-    DoNotExternalize
-};
+
+void* v8DOMWrapperToNative(v8::Handle<v8::Object> object) {
+    return object->GetPointerFromInternalField(V8Custom::kDOMWrapperObjectIndex);
+}
+    
+void* v8DOMWrapperToNative(const v8::AccessorInfo& info) {
+    return info.Holder()->GetPointerFromInternalField(V8Custom::kDOMWrapperObjectIndex);
+}
+    
+
+String v8ValueToWebCoreString(v8::Handle<v8::Value> value)
+{
+    if (value->IsString())
+        return v8StringToWebCoreString(v8::Handle<v8::String>::Cast(value));
+    return v8NonStringValueToWebCoreString(value);
+}
+
+AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> value)
+{
+    if (value->IsString())
+        return v8StringToAtomicWebCoreString(v8::Handle<v8::String>::Cast(value));
+    return v8NonStringValueToAtomicWebCoreString(value);
+}
+
+int toInt32(v8::Handle<v8::Value> value, bool& ok)
+{
+    ok = true;
+    
+    // Fast case.  The value is already a 32-bit integer.
+    if (value->IsInt32())
+        return value->Int32Value();
+    
+    // Can the value be converted to a number?
+    v8::Local<v8::Number> numberObject = value->ToNumber();
+    if (numberObject.IsEmpty()) {
+        ok = false;
+        return 0;
+    }
+    
+    // Does the value convert to nan or to an infinity?
+    double numberValue = numberObject->Value();
+    if (isnan(numberValue) || isinf(numberValue)) {
+        ok = false;
+        return 0;
+    }
+    
+    // Can the value be converted to a 32-bit integer?
+    v8::Local<v8::Int32> intValue = value->ToInt32();
+    if (intValue.IsEmpty()) {
+        ok = false;
+        return 0;
+    }
+    
+    // Return the result of the int32 conversion.
+    return intValue->Value();
+}
+    
+String toWebCoreString(const v8::Arguments& args, int index) {
+    return v8ValueToWebCoreString(args[index]);
+}
+
+    
+String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value)
+{
+    if (value->IsNull()) 
+        return String();
+    return v8ValueToWebCoreString(value);
+}
+
+AtomicString toAtomicWebCoreStringWithNullCheck(v8::Handle<v8::Value> value)
+{
+    if (value->IsNull())
+        return AtomicString();
+    return v8ValueToAtomicWebCoreString(value);
+}
+
+String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value)
+{
+    if (value->IsNull() || value->IsUndefined())
+        return String();
+    return toWebCoreString(value);
+}
+
+bool isUndefinedOrNull(v8::Handle<v8::Value> value)
+{
+    return value->IsNull() || value->IsUndefined();
+}
+
+v8::Handle<v8::Boolean> v8Boolean(bool value)
+{
+    return value ? v8::True() : v8::False();
+}
+
+v8::Handle<v8::String> v8UndetectableString(const String& str)
+{
+    return v8::String::NewUndetectable(fromWebCoreString(str), str.length());
+}
+
+v8::Handle<v8::Value> v8StringOrNull(const String& str)
+{
+    return str.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::Value>(v8String(str));
+}
+
+v8::Handle<v8::Value> v8StringOrUndefined(const String& str)
+{
+    return str.isNull() ? v8::Handle<v8::Value>(v8::Undefined()) : v8::Handle<v8::Value>(v8String(str));
+}
+
+v8::Handle<v8::Value> v8StringOrFalse(const String& str)
+{
+    return str.isNull() ? v8::Handle<v8::Value>(v8::False()) : v8::Handle<v8::Value>(v8String(str));
+}
+
 
 template <typename StringType>
-static StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external)
+StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external)
 {
     WebCoreStringResource* stringResource = WebCoreStringResource::toStringResource(v8String);
     if (stringResource)
@@ -169,16 +278,6 @@ static StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, Exter
     return result;
 }
 
-String v8StringToWebCoreString(v8::Handle<v8::String> v8String)
-{
-    return v8StringToWebCoreString<String>(v8String, Externalize);
-}
-
-AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String)
-{
-    return v8StringToWebCoreString<AtomicString>(v8String, Externalize);
-}
-
 String v8NonStringValueToWebCoreString(v8::Handle<v8::Value> object)
 {
     ASSERT(!object->IsString());
@@ -254,13 +353,13 @@ static void cachedStringCallback(v8::Persistent<v8::Value> wrapper, void* parame
 
 v8::Local<v8::String> v8ExternalString(const String& string)
 {
-    if (!string.length())
+    StringImpl* stringImpl = string.impl();
+    if (!stringImpl || !stringImpl->length())
         return v8::String::Empty();
 
     if (!stringImplCacheEnabled)
         return makeExternalString(string);
 
-    StringImpl* stringImpl = string.impl();
     StringCache& stringCache = getStringCache();
     v8::String* cachedV8String = stringCache.get(stringImpl);
     if (cachedV8String)
@@ -280,5 +379,12 @@ v8::Local<v8::String> v8ExternalString(const String& string)
 
     return newString;
 }
+    
+v8::Persistent<v8::FunctionTemplate> createRawTemplate()
+{
+    v8::HandleScope scope;
+    v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(V8Proxy::checkNewLegal);
+    return v8::Persistent<v8::FunctionTemplate>::New(result);
+}        
 
 } // namespace WebCore
index 237bc4d7c61478a5c5cc317f8035bb4d88917672..4447453fdef3a408f1aaff37fd5b778941ea20b6 100644 (file)
 #include "AtomicString.h"
 #include "MathExtras.h"
 #include "PlatformString.h"
+#include "V8DOMWrapper.h"
+#include "V8Index.h"
 
 #include <v8.h>
 
 namespace WebCore {
+    
+    class EventListener;
+    class EventTarget;
+    
+    // A helper function extract native object pointer from a DOM wrapper
+    // and cast to the specified type.
+    void* v8DOMWrapperToNative(v8::Handle<v8::Object>);
+    
+    template <class C>
+    C* v8DOMWrapperTo(v8::Handle<v8::Object> object)
+    {
+        ASSERT(V8DOMWrapper::maybeDOMWrapper(object));
+        return reinterpret_cast<C*>(v8DOMWrapperToNative(object));
+    }
+    template <class C>
+    C* v8DOMWrapperToNode(v8::Handle<v8::Object> object)
+    {
+        ASSERT(V8DOMWrapper::maybeDOMWrapper(object));
+        ASSERT(V8DOMWrapper::domWrapperType(object) == V8ClassIndex::NODE);
+        return reinterpret_cast<C*>(v8DOMWrapperToNative(object));
+    }
+    
+    void* v8DOMWrapperToNative(const v8::AccessorInfo&);
+    
+    template <class C>
+    C* v8DOMWrapperTo(const v8::AccessorInfo& info) {
+        ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder()));
+        return reinterpret_cast<C*>(v8DOMWrapperToNative(info));
+    }
+    template <class C>
+    C* v8DOMWrapperToNode(const v8::AccessorInfo& info) {
+        ASSERT(V8DOMWrapper::domWrapperType(info.Holder()) == V8ClassIndex::NODE);
+        return reinterpret_cast<C*>(v8DOMWrapperToNative(info));
+    }
+    
+    template <class C>
+    C* v8DOMWrapperTo(V8ClassIndex::V8WrapperType type, v8::Handle<v8::Object> object)
+    {
+        // Native event listener is per frame, it cannot be handled by this generic function.
+        ASSERT(type != V8ClassIndex::EVENTLISTENER);
+        ASSERT(type != V8ClassIndex::EVENTTARGET);
+        
+        ASSERT(V8DOMWrapper::maybeDOMWrapper(object));
+        
+#ifndef NDEBUG
+        const bool typeIsValid =
+#define MAKE_CASE(TYPE, NAME) (type != V8ClassIndex::TYPE) &&
+        DOM_NODE_TYPES(MAKE_CASE)
+#if ENABLE(SVG)
+        SVG_NODE_TYPES(MAKE_CASE)
+#endif
+#undef MAKE_CASE
+        true;
+        ASSERT(typeIsValid);
+#endif
+        
+        return v8DOMWrapperTo<C>(object);
+    }
+    
+    template <class C>
+    C* v8DOMWrapperTo(V8ClassIndex::V8WrapperType type, const v8::AccessorInfo& info)
+    {
+#ifndef NDEBUG
+        return v8DOMWrapperTo<C>(type, info.Holder());
+#else
+        return reinterpret_cast<C*>(v8DOMWrapperToNative(info));
+#endif
+    }
+
+    
+    enum ExternalMode {
+        Externalize,
+        DoNotExternalize
+    };
+    
+    template <typename StringType>
+    StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external);
 
     // Convert v8 types to a WebCore::String. If the V8 string is not already
     // an external string then it is transformed into an external string at this
     // point to avoid repeated conversions.
-    String v8StringToWebCoreString(v8::Handle<v8::String>);
-    String v8NonStringValueToWebCoreString(v8::Handle<v8::Value>);
-    inline String v8ValueToWebCoreString(v8::Handle<v8::Value> value)
+    inline String v8StringToWebCoreString(v8::Handle<v8::String> v8String)
     {
-        if (value->IsString())
-            return v8StringToWebCoreString(v8::Handle<v8::String>::Cast(value));
-        return v8NonStringValueToWebCoreString(value);
+        return v8StringToWebCoreString<String>(v8String, Externalize);
     }
+    String v8NonStringValueToWebCoreString(v8::Handle<v8::Value>);
+    String v8ValueToWebCoreString(v8::Handle<v8::Value> value);
 
     // Convert v8 types to a WebCore::AtomicString.
-    AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String>);
-    AtomicString v8NonStringValueToAtomicWebCoreString(v8::Handle<v8::Value>);
-    inline AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> value)
+    inline AtomicString v8StringToAtomicWebCoreString(v8::Handle<v8::String> v8String)
     {
-        if (value->IsString())
-            return v8StringToAtomicWebCoreString(v8::Handle<v8::String>::Cast(value));
-        return v8NonStringValueToAtomicWebCoreString(value);
-    }
-
-    inline const String& toString(const String& string)
-    {
-        return string;
+        return v8StringToWebCoreString<AtomicString>(v8String, Externalize);
     }
+    AtomicString v8NonStringValueToAtomicWebCoreString(v8::Handle<v8::Value>);
+    AtomicString v8ValueToAtomicWebCoreString(v8::Handle<v8::Value> value);
 
     // Return a V8 external string that shares the underlying buffer with the given
     // WebCore string. The reference counting mechanism is used to keep the
@@ -84,38 +154,7 @@ namespace WebCore {
 
     // Convert a value to a 32-bit integer.  The conversion fails if the
     // value cannot be converted to an integer or converts to nan or to an infinity.
-    inline int toInt32(v8::Handle<v8::Value> value, bool& ok)
-    {
-        ok = true;
-
-        // Fast case.  The value is already a 32-bit integer.
-        if (value->IsInt32())
-            return value->Int32Value();
-
-        // Can the value be converted to a number?
-        v8::Local<v8::Number> numberObject = value->ToNumber();
-        if (numberObject.IsEmpty()) {
-            ok = false;
-            return 0;
-        }
-
-        // Does the value convert to nan or to an infinity?
-        double numberValue = numberObject->Value();
-        if (isnan(numberValue) || isinf(numberValue)) {
-            ok = false;
-            return 0;
-        }
-
-        // Can the value be converted to a 32-bit integer?
-        v8::Local<v8::Int32> intValue = value->ToInt32();
-        if (intValue.IsEmpty()) {
-            ok = false;
-            return 0;
-        }
-
-        // Return the result of the int32 conversion.
-        return intValue->Value();
-    }
+    int toInt32(v8::Handle<v8::Value> value, bool& ok);
 
     // Convert a value to a 32-bit integer assuming the conversion cannot fail.
     inline int toInt32(v8::Handle<v8::Value> value)
@@ -134,6 +173,8 @@ namespace WebCore {
     {
         return v8ValueToWebCoreString(object);
     }
+    
+    String toWebCoreString(const v8::Arguments&, int index);
 
     // The string returned by this function is still owned by the argument
     // and will be deallocated when the argument is deallocated.
@@ -142,56 +183,26 @@ namespace WebCore {
         return reinterpret_cast<const uint16_t*>(str.characters());
     }
 
-    inline bool isUndefinedOrNull(v8::Handle<v8::Value> value)
-    {
-        return value->IsNull() || value->IsUndefined();
-    }
+    bool isUndefinedOrNull(v8::Handle<v8::Value> value);
 
-    inline v8::Handle<v8::Boolean> v8Boolean(bool value)
-    {
-        return value ? v8::True() : v8::False();
-    }
+    v8::Handle<v8::Boolean> v8Boolean(bool value);
 
-    inline String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value)
-    {
-        if (value->IsNull()) 
-            return String();
-        return v8ValueToWebCoreString(value);
-    }
+    String toWebCoreStringWithNullCheck(v8::Handle<v8::Value> value);
 
-    inline AtomicString v8ValueToAtomicWebCoreStringWithNullCheck(v8::Handle<v8::Value> value)
-    {
-        if (value->IsNull())
-            return AtomicString();
-        return v8ValueToAtomicWebCoreString(value);
-    }
+    AtomicString toAtomicWebCoreStringWithNullCheck(v8::Handle<v8::Value> value);
 
-    inline String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value)
-    {
-        if (value->IsNull() || value->IsUndefined())
-            return String();
-        return toWebCoreString(value);
-    }
+    String toWebCoreStringWithNullOrUndefinedCheck(v8::Handle<v8::Value> value);
  
-    inline v8::Handle<v8::String> v8UndetectableString(const String& str)
-    {
-        return v8::String::NewUndetectable(fromWebCoreString(str), str.length());
-    }
+    v8::Handle<v8::String> v8UndetectableString(const String& str);
 
-    inline v8::Handle<v8::Value> v8StringOrNull(const String& str)
-    {
-        return str.isNull() ? v8::Handle<v8::Value>(v8::Null()) : v8::Handle<v8::Value>(v8String(str));
-    }
+    v8::Handle<v8::Value> v8StringOrNull(const String& str);
 
-    inline v8::Handle<v8::Value> v8StringOrUndefined(const String& str)
-    {
-        return str.isNull() ? v8::Handle<v8::Value>(v8::Undefined()) : v8::Handle<v8::Value>(v8String(str));
-    }
+    v8::Handle<v8::Value> v8StringOrUndefined(const String& str);
+
+    v8::Handle<v8::Value> v8StringOrFalse(const String& str);
+    
+    v8::Persistent<v8::FunctionTemplate> createRawTemplate();
 
-    inline v8::Handle<v8::Value> v8StringOrFalse(const String& str)
-    {
-        return str.isNull() ? v8::Handle<v8::Value>(v8::False()) : v8::Handle<v8::Value>(v8String(str));
-    }
 } // namespace WebCore
 
 #endif // V8Binding_h