[JSC] Add inherits<T>(VM&) leveraging JSCast fast path
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Mar 2018 16:06:48 +0000 (16:06 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 8 Mar 2018 16:06:48 +0000 (16:06 +0000)
https://bugs.webkit.org/show_bug.cgi?id=183429

Reviewed by Mark Lam.

Source/JavaScriptCore:

Add new member function, JSCell::inherits<T>(VM&) and JSValue::inherits<T>(VM&).
They depends on jsDynamicCast<T> implementation and leverage JSType-based fast
paths defined in JSCast.h. We extract checking part as `JSCastingHelpers::inherit`
and construct jsDynamicCast and JSCell::inherits based on this.

And we remove several unnecessary casting functions (asRegExpObject, asDateInstance etc.).
In addition, we add jsDynamicCast fast path for RegExpObject by using existing RegExpObjectType.

We also fix the implementation of jsDynamicCast for JSObject since it uses LastJSCObjectType.
The embedder can add their extended object types after that.

* API/JSObjectRef.cpp:
(JSObjectGetPrivateProperty):
(JSObjectSetPrivateProperty):
(JSObjectDeletePrivateProperty):
* API/JSValue.mm:
(isDate):
(isArray):
* API/JSValueRef.cpp:
(JSValueIsArray):
(JSValueIsDate):
(JSValueIsObjectOfClass):
* API/JSWeakObjectMapRefPrivate.cpp:
* API/JSWrapperMap.mm:
(tryUnwrapObjcObject):
* API/ObjCCallbackFunction.mm:
(tryUnwrapConstructor):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGOperations.cpp:
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileOverridesHasInstance):
(JSC::FTL::DFG::LowerDFGToB3::compileNewRegexp):
* ftl/FTLOperations.cpp:
(JSC::FTL::operationMaterializeObjectInOSR):
* inspector/JSInjectedScriptHost.cpp:
(Inspector::JSInjectedScriptHost::subtype):
(Inspector::JSInjectedScriptHost::functionDetails):
* inspector/agents/InspectorHeapAgent.cpp:
(Inspector::InspectorHeapAgent::getPreview):
* interpreter/Interpreter.cpp:
(JSC::notifyDebuggerOfUnwinding):
* interpreter/ShadowChicken.cpp:
(JSC::ShadowChicken::update):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JITOperations.cpp:
(JSC::operationNewFunctionCommon):
* jsc.cpp:
(checkException):
* runtime/BooleanObject.h:
(JSC::asBooleanObject): Deleted.
* runtime/BooleanPrototype.cpp:
(JSC::booleanProtoFuncToString):
(JSC::booleanProtoFuncValueOf):
* runtime/DateConstructor.cpp:
(JSC::constructDate):
* runtime/DateInstance.h:
(JSC::asDateInstance): Deleted.
* runtime/DatePrototype.cpp:
(JSC::formateDateInstance):
(JSC::dateProtoFuncToISOString):
(JSC::dateProtoFuncToLocaleString):
(JSC::dateProtoFuncToLocaleDateString):
(JSC::dateProtoFuncToLocaleTimeString):
(JSC::dateProtoFuncGetTime):
(JSC::dateProtoFuncGetFullYear):
(JSC::dateProtoFuncGetUTCFullYear):
(JSC::dateProtoFuncGetMonth):
(JSC::dateProtoFuncGetUTCMonth):
(JSC::dateProtoFuncGetDate):
(JSC::dateProtoFuncGetUTCDate):
(JSC::dateProtoFuncGetDay):
(JSC::dateProtoFuncGetUTCDay):
(JSC::dateProtoFuncGetHours):
(JSC::dateProtoFuncGetUTCHours):
(JSC::dateProtoFuncGetMinutes):
(JSC::dateProtoFuncGetUTCMinutes):
(JSC::dateProtoFuncGetSeconds):
(JSC::dateProtoFuncGetUTCSeconds):
(JSC::dateProtoFuncGetMilliSeconds):
(JSC::dateProtoFuncGetUTCMilliseconds):
(JSC::dateProtoFuncGetTimezoneOffset):
(JSC::dateProtoFuncSetTime):
(JSC::setNewValueFromTimeArgs):
(JSC::setNewValueFromDateArgs):
(JSC::dateProtoFuncSetYear):
(JSC::dateProtoFuncGetYear):
* runtime/ExceptionHelpers.cpp:
(JSC::isTerminatedExecutionException):
* runtime/FunctionPrototype.cpp:
(JSC::functionProtoFuncToString):
* runtime/InternalFunction.h:
(JSC::asInternalFunction):
* runtime/JSArray.h:
(JSC::asArray):
* runtime/JSCJSValue.cpp:
(JSC::JSValue::dumpForBacktrace const):
* runtime/JSCJSValue.h:
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::inherits const):
* runtime/JSCast.h:
(JSC::JSCastingHelpers::inheritsGenericImpl):
(JSC::JSCastingHelpers::inheritsJSTypeImpl):
(JSC::JSCastingHelpers::InheritsTraits::inherits):
(JSC::JSCastingHelpers::inherits):
(JSC::jsDynamicCast):
(JSC::JSCastingHelpers::jsDynamicCastGenericImpl): Deleted.
(JSC::JSCastingHelpers::jsDynamicCastJSTypeImpl): Deleted.
(JSC::JSCastingHelpers::JSDynamicCastTraits::cast): Deleted.
* runtime/JSCell.h:
* runtime/JSCellInlines.h:
(JSC::JSCell::inherits const):
* runtime/JSFunction.cpp:
(JSC::RetrieveCallerFunctionFunctor::operator() const):
(JSC::JSFunction::callerGetter):
(JSC::JSFunction::getOwnNonIndexPropertyNames):
(JSC::JSFunction::reifyLazyBoundNameIfNeeded):
* runtime/JSGlobalObject.cpp:
(JSC::enqueueJob):
* runtime/JSGlobalObject.h:
(JSC::asGlobalObject): Deleted.
* runtime/JSInternalPromiseDeferred.cpp:
(JSC::JSInternalPromiseDeferred::create):
* runtime/JSLexicalEnvironment.h:
(JSC::asActivation):
* runtime/JSONObject.cpp:
(JSC::unwrapBoxedPrimitive):
(JSC::Stringifier::Stringifier):
(JSC::Walker::walk):
* runtime/JSPromise.cpp:
(JSC::JSPromise::resolve):
* runtime/JSPromiseDeferred.cpp:
(JSC::JSPromiseDeferred::create):
* runtime/JSType.h:
* runtime/ProxyObject.h:
(JSC::ProxyObject::create): Deleted.
(JSC::ProxyObject::createStructure): Deleted.
(JSC::ProxyObject::target const): Deleted.
(JSC::ProxyObject::handler const): Deleted.
* runtime/RegExpConstructor.cpp:
(JSC::constructRegExp):
* runtime/RegExpConstructor.h:
(JSC::asRegExpConstructor):
(JSC::isRegExp):
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::finishCreation):
(JSC::RegExpObject::getOwnPropertySlot):
(JSC::RegExpObject::defineOwnProperty):
(JSC::regExpObjectSetLastIndexStrict):
(JSC::regExpObjectSetLastIndexNonStrict):
(JSC::RegExpObject::put):
* runtime/RegExpObject.h:
(JSC::RegExpObject::create): Deleted.
(JSC::RegExpObject::setRegExp): Deleted.
(JSC::RegExpObject::regExp const): Deleted.
(JSC::RegExpObject::setLastIndex): Deleted.
(JSC::RegExpObject::getLastIndex const): Deleted.
(JSC::RegExpObject::test): Deleted.
(JSC::RegExpObject::testInline): Deleted.
(JSC::RegExpObject::createStructure): Deleted.
(JSC::RegExpObject::offsetOfRegExp): Deleted.
(JSC::RegExpObject::offsetOfLastIndex): Deleted.
(JSC::RegExpObject::offsetOfLastIndexIsWritable): Deleted.
(JSC::RegExpObject::allocationSize): Deleted.
(JSC::asRegExpObject): Deleted.
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncTestFast):
(JSC::regExpProtoFuncExec):
(JSC::regExpProtoFuncMatchFast):
(JSC::regExpProtoFuncCompile):
(JSC::regExpProtoGetterGlobal):
(JSC::regExpProtoGetterIgnoreCase):
(JSC::regExpProtoGetterMultiline):
(JSC::regExpProtoGetterDotAll):
(JSC::regExpProtoGetterSticky):
(JSC::regExpProtoGetterUnicode):
(JSC::regExpProtoGetterSource):
(JSC::regExpProtoFuncSearchFast):
(JSC::regExpProtoFuncSplitFast):
* runtime/StringObject.h:
(JSC::asStringObject): Deleted.
* runtime/StringPrototype.cpp:
(JSC::replaceUsingRegExpSearch):
(JSC::replace):
(JSC::stringProtoFuncReplaceUsingRegExp):
(JSC::stringProtoFuncToString):
* runtime/SymbolPrototype.cpp:
(JSC::symbolProtoFuncToString):
(JSC::symbolProtoFuncValueOf):
* tools/JSDollarVM.cpp:
(WTF::customGetValue):
(WTF::customSetValue):
* wasm/js/JSWebAssemblyHelpers.h:
(JSC::isWebAssemblyHostFunction):
* wasm/js/WebAssemblyWrapperFunction.cpp:
(JSC::WebAssemblyWrapperFunction::create):

Source/WebCore:

* bindings/js/IDBBindingUtilities.cpp:
(WebCore::createIDBKeyFromValue):
* bindings/js/JSDOMConvertDate.cpp:
(WebCore::valueToDate):
* bindings/js/JSDOMGlobalObject.cpp:
(WebCore::JSDOMGlobalObject::scriptExecutionContext const):
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::toWrapped):
* bindings/js/JSEventTargetCustom.cpp:
* bindings/js/JSNodeCustom.cpp:
(WebCore::JSNode::pushEventHandlerScope const):
* bindings/js/JSXPathNSResolverCustom.cpp:
(WebCore::JSXPathNSResolver::toWrapped):
* bindings/js/ScriptState.cpp:
(WebCore::domWindowFromExecState):
(WebCore::scriptExecutionContextFromExecState):
* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::isArray):
(WebCore::CloneSerializer::isMap):
(WebCore::CloneSerializer::isSet):
(WebCore::CloneSerializer::dumpArrayBufferView):
(WebCore::CloneSerializer::dumpDOMPoint):
(WebCore::CloneSerializer::dumpDOMRect):
(WebCore::CloneSerializer::dumpDOMMatrix):
(WebCore::CloneSerializer::dumpIfTerminal):
(WebCore::CloneDeserializer::CloneDeserializer):
(WebCore::CloneDeserializer::readArrayBufferView):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateOverloadDispatcher):
* bindings/scripts/test/JS/JSTestObj.cpp:
(WebCore::jsTestObjPrototypeFunctionOverloadedMethodOverloadDispatcher):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameterOverloadDispatcher):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnionOverloadDispatcher):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnionsOverloadDispatcher):
(WebCore::jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnionOverloadDispatcher):
(WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnionOverloadDispatcher):
(WebCore::jsTestObjPrototypeFunctionOverloadWithNullableNonDistinguishingParameterOverloadDispatcher):
(WebCore::jsTestObjPrototypeFunctionTestPromiseOverloadedFunctionOverloadDispatcher):
* bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp:
(WebCore::JSTestOverloadedConstructorsConstructor::construct):
* bridge/c/c_instance.cpp:
(JSC::Bindings::CInstance::invokeMethod):
* bridge/objc/WebScriptObject.mm:
(+[WebScriptObject _convertValueToObjcValue:originRootObject:rootObject:]):
* bridge/objc/objc_instance.mm:
(ObjcInstance::invokeMethod):
* bridge/objc/objc_runtime.mm:
(JSC::Bindings::callObjCFallbackObject):
* bridge/runtime_method.cpp:
(JSC::callRuntimeMethod):
* bridge/runtime_object.cpp:
(JSC::Bindings::callRuntimeObject):
(JSC::Bindings::callRuntimeConstructor):
* inspector/WebInjectedScriptHost.cpp:
(WebCore::WebInjectedScriptHost::subtype):
(WebCore::WebInjectedScriptHost::isHTMLAllCollection):

Source/WebKit:

* WebProcess/Plugins/Netscape/JSNPMethod.cpp:
(WebKit::callMethod):
* WebProcess/Plugins/Netscape/JSNPObject.cpp:
(WebKit::callNPJSObject):
(WebKit::constructWithConstructor):
* WebProcess/Plugins/Netscape/NPJSObject.cpp:
(WebKit::NPJSObject::create):
* WebProcess/WebPage/WebFrame.cpp:
(WebKit::WebFrame::counterValue):

Source/WebKitLegacy/mac:

* DOM/DOM.mm:
(+[DOMNode _nodeFromJSWrapper:]):
* Plugins/Hosted/NetscapePluginInstanceProxy.mm:
(WebKit::NetscapePluginInstanceProxy::retainLocalObject):
(WebKit::NetscapePluginInstanceProxy::releaseLocalObject):
* Plugins/Hosted/ProxyInstance.mm:
(WebKit::ProxyInstance::invokeMethod):
* WebView/WebView.mm:
(aeDescFromJSValue):

Source/WebKitLegacy/win:

* WebFrame.cpp:
(WebFrame::stringByEvaluatingJavaScriptInScriptWorld):

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

86 files changed:
Source/JavaScriptCore/API/JSObjectRef.cpp
Source/JavaScriptCore/API/JSValue.mm
Source/JavaScriptCore/API/JSValueRef.cpp
Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp
Source/JavaScriptCore/API/JSWrapperMap.mm
Source/JavaScriptCore/API/ObjCCallbackFunction.mm
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/ftl/FTLOperations.cpp
Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp
Source/JavaScriptCore/inspector/agents/InspectorHeapAgent.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/interpreter/ShadowChicken.cpp
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/runtime/BooleanObject.h
Source/JavaScriptCore/runtime/BooleanPrototype.cpp
Source/JavaScriptCore/runtime/DateConstructor.cpp
Source/JavaScriptCore/runtime/DateInstance.h
Source/JavaScriptCore/runtime/DatePrototype.cpp
Source/JavaScriptCore/runtime/ExceptionHelpers.cpp
Source/JavaScriptCore/runtime/FunctionPrototype.cpp
Source/JavaScriptCore/runtime/InternalFunction.h
Source/JavaScriptCore/runtime/JSArray.h
Source/JavaScriptCore/runtime/JSCJSValue.cpp
Source/JavaScriptCore/runtime/JSCJSValue.h
Source/JavaScriptCore/runtime/JSCJSValueInlines.h
Source/JavaScriptCore/runtime/JSCast.h
Source/JavaScriptCore/runtime/JSCell.h
Source/JavaScriptCore/runtime/JSCellInlines.h
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.cpp
Source/JavaScriptCore/runtime/JSGlobalObject.h
Source/JavaScriptCore/runtime/JSInternalPromiseDeferred.cpp
Source/JavaScriptCore/runtime/JSLexicalEnvironment.h
Source/JavaScriptCore/runtime/JSONObject.cpp
Source/JavaScriptCore/runtime/JSPromise.cpp
Source/JavaScriptCore/runtime/JSPromiseDeferred.cpp
Source/JavaScriptCore/runtime/JSType.h
Source/JavaScriptCore/runtime/ProxyObject.h
Source/JavaScriptCore/runtime/RegExpConstructor.cpp
Source/JavaScriptCore/runtime/RegExpConstructor.h
Source/JavaScriptCore/runtime/RegExpObject.cpp
Source/JavaScriptCore/runtime/RegExpObject.h
Source/JavaScriptCore/runtime/RegExpPrototype.cpp
Source/JavaScriptCore/runtime/StringObject.h
Source/JavaScriptCore/runtime/StringPrototype.cpp
Source/JavaScriptCore/runtime/SymbolPrototype.cpp
Source/JavaScriptCore/tools/JSDollarVM.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h
Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.cpp
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/IDBBindingUtilities.cpp
Source/WebCore/bindings/js/JSDOMConvertDate.cpp
Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
Source/WebCore/bindings/js/JSEventTargetCustom.cpp
Source/WebCore/bindings/js/JSNodeCustom.cpp
Source/WebCore/bindings/js/JSXPathNSResolverCustom.cpp
Source/WebCore/bindings/js/ScriptState.cpp
Source/WebCore/bindings/js/SerializedScriptValue.cpp
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp
Source/WebCore/bridge/c/c_instance.cpp
Source/WebCore/bridge/objc/WebScriptObject.mm
Source/WebCore/bridge/objc/objc_instance.mm
Source/WebCore/bridge/objc/objc_runtime.mm
Source/WebCore/bridge/runtime_method.cpp
Source/WebCore/bridge/runtime_object.cpp
Source/WebCore/inspector/WebInjectedScriptHost.cpp
Source/WebKit/ChangeLog
Source/WebKit/WebProcess/Plugins/Netscape/JSNPMethod.cpp
Source/WebKit/WebProcess/Plugins/Netscape/JSNPObject.cpp
Source/WebKit/WebProcess/Plugins/Netscape/NPJSObject.cpp
Source/WebKit/WebProcess/WebPage/WebFrame.cpp
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/DOM/DOM.mm
Source/WebKitLegacy/mac/Plugins/Hosted/NetscapePluginInstanceProxy.mm
Source/WebKitLegacy/mac/Plugins/Hosted/ProxyInstance.mm
Source/WebKitLegacy/mac/WebView/WebView.mm
Source/WebKitLegacy/win/ChangeLog
Source/WebKitLegacy/win/WebFrame.cpp

index 6747337..4f88681 100644 (file)
@@ -501,15 +501,15 @@ JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSSt
 
 
     // Get wrapped object if proxied
-    if (jsObject->inherits(vm, JSProxy::info()))
+    if (jsObject->inherits<JSProxy>(vm))
         jsObject = jsCast<JSProxy*>(jsObject)->target();
 
-    if (jsObject->inherits(vm, JSCallbackObject<JSGlobalObject>::info()))
+    if (jsObject->inherits<JSCallbackObject<JSGlobalObject>>(vm))
         result = jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
-    else if (jsObject->inherits(vm, JSCallbackObject<JSDestructibleObject>::info()))
+    else if (jsObject->inherits<JSCallbackObject<JSDestructibleObject>>(vm))
         result = jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivateProperty(name);
 #if JSC_OBJC_API_ENABLED
-    else if (jsObject->inherits(vm, JSCallbackObject<JSAPIWrapperObject>::info()))
+    else if (jsObject->inherits<JSCallbackObject<JSAPIWrapperObject>>(vm))
         result = jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivateProperty(name);
 #endif
     return toRef(exec, result);
@@ -525,19 +525,19 @@ bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRe
     Identifier name(propertyName->identifier(&vm));
 
     // Get wrapped object if proxied
-    if (jsObject->inherits(vm, JSProxy::info()))
+    if (jsObject->inherits<JSProxy>(vm))
         jsObject = jsCast<JSProxy*>(jsObject)->target();
 
-    if (jsObject->inherits(vm, JSCallbackObject<JSGlobalObject>::info())) {
+    if (jsObject->inherits<JSCallbackObject<JSGlobalObject>>(vm)) {
         jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(vm, name, jsValue);
         return true;
     }
-    if (jsObject->inherits(vm, JSCallbackObject<JSDestructibleObject>::info())) {
+    if (jsObject->inherits<JSCallbackObject<JSDestructibleObject>>(vm)) {
         jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivateProperty(vm, name, jsValue);
         return true;
     }
 #if JSC_OBJC_API_ENABLED
-    if (jsObject->inherits(vm, JSCallbackObject<JSAPIWrapperObject>::info())) {
+    if (jsObject->inherits<JSCallbackObject<JSAPIWrapperObject>>(vm)) {
         jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivateProperty(vm, name, jsValue);
         return true;
     }
@@ -554,19 +554,19 @@ bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStrin
     Identifier name(propertyName->identifier(&vm));
 
     // Get wrapped object if proxied
-    if (jsObject->inherits(vm, JSProxy::info()))
+    if (jsObject->inherits<JSProxy>(vm))
         jsObject = jsCast<JSProxy*>(jsObject)->target();
 
-    if (jsObject->inherits(vm, JSCallbackObject<JSGlobalObject>::info())) {
+    if (jsObject->inherits<JSCallbackObject<JSGlobalObject>>(vm)) {
         jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name);
         return true;
     }
-    if (jsObject->inherits(vm, JSCallbackObject<JSDestructibleObject>::info())) {
+    if (jsObject->inherits<JSCallbackObject<JSDestructibleObject>>(vm)) {
         jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->deletePrivateProperty(name);
         return true;
     }
 #if JSC_OBJC_API_ENABLED
-    if (jsObject->inherits(vm, JSCallbackObject<JSAPIWrapperObject>::info())) {
+    if (jsObject->inherits<JSCallbackObject<JSAPIWrapperObject>>(vm)) {
         jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->deletePrivateProperty(name);
         return true;
     }
index 6f3b1d8..c810f14 100644 (file)
@@ -574,13 +574,13 @@ NSString * const JSPropertyDescriptorSetKey = @"set";
 inline bool isDate(JSC::VM& vm, JSObjectRef object, JSGlobalContextRef context)
 {
     JSC::JSLockHolder locker(toJS(context));
-    return toJS(object)->inherits(vm, JSC::DateInstance::info());
+    return toJS(object)->inherits<JSC::DateInstance>(vm);
 }
 
 inline bool isArray(JSC::VM& vm, JSObjectRef object, JSGlobalContextRef context)
 {
     JSC::JSLockHolder locker(toJS(context));
-    return toJS(object)->inherits(vm, JSC::JSArray::info());
+    return toJS(object)->inherits<JSC::JSArray>(vm);
 }
 
 @implementation JSValue(Internal)
index 23dbc72..00bf061 100644 (file)
@@ -172,7 +172,7 @@ bool JSValueIsArray(JSContextRef ctx, JSValueRef value)
     VM& vm = exec->vm();
     JSLockHolder locker(exec);
 
-    return toJS(exec, value).inherits(vm, JSArray::info());
+    return toJS(exec, value).inherits<JSArray>(vm);
 }
 
 bool JSValueIsDate(JSContextRef ctx, JSValueRef value)
@@ -185,7 +185,7 @@ bool JSValueIsDate(JSContextRef ctx, JSValueRef value)
     VM& vm = exec->vm();
     JSLockHolder locker(exec);
 
-    return toJS(exec, value).inherits(vm, DateInstance::info());
+    return toJS(exec, value).inherits<DateInstance>(vm);
 }
 
 bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass)
@@ -201,15 +201,15 @@ bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsCla
     JSValue jsValue = toJS(exec, value);
     
     if (JSObject* o = jsValue.getObject()) {
-        if (o->inherits(vm, JSProxy::info()))
+        if (o->inherits<JSProxy>(vm))
             o = jsCast<JSProxy*>(o)->target();
 
-        if (o->inherits(vm, JSCallbackObject<JSGlobalObject>::info()))
+        if (o->inherits<JSCallbackObject<JSGlobalObject>>(vm))
             return jsCast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass);
-        if (o->inherits(vm, JSCallbackObject<JSDestructibleObject>::info()))
+        if (o->inherits<JSCallbackObject<JSDestructibleObject>>(vm))
             return jsCast<JSCallbackObject<JSDestructibleObject>*>(o)->inherits(jsClass);
 #if JSC_OBJC_API_ENABLED
-        if (o->inherits(vm, JSCallbackObject<JSAPIWrapperObject>::info()))
+        if (o->inherits<JSCallbackObject<JSAPIWrapperObject>>(vm))
             return jsCast<JSCallbackObject<JSAPIWrapperObject>*>(o)->inherits(jsClass);
 #endif
     }
index 7f1cd52..78332d7 100644 (file)
@@ -63,9 +63,9 @@ void JSWeakObjectMapSet(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSO
     JSObject* obj = toJS(object);
     if (!obj)
         return;
-    ASSERT(obj->inherits(vm, JSProxy::info())
-        || obj->inherits(vm, JSCallbackObject<JSGlobalObject>::info())
-        || obj->inherits(vm, JSCallbackObject<JSDestructibleObject>::info()));
+    ASSERT(obj->inherits<JSProxy>(vm)
+        || obj->inherits<JSCallbackObject<JSGlobalObject>>(vm)
+        || obj->inherits<JSCallbackObject<JSDestructibleObject>>(vm));
     map->map().set(key, obj);
 }
 
index 9425195..4f5a13b 100644 (file)
@@ -644,7 +644,7 @@ id tryUnwrapObjcObject(JSGlobalContextRef context, JSValueRef value)
     ASSERT(!exception);
     JSC::JSLockHolder locker(toJS(context));
     JSC::VM& vm = toJS(context)->vm();
-    if (toJS(object)->inherits(vm, JSC::JSCallbackObject<JSC::JSAPIWrapperObject>::info()))
+    if (toJS(object)->inherits<JSC::JSCallbackObject<JSC::JSAPIWrapperObject>>(vm))
         return (id)JSC::jsCast<JSC::JSAPIWrapperObject*>(toJS(object))->wrappedObject();
     if (id target = tryUnwrapConstructor(&vm, object))
         return target;
index 63f920e..a88a270 100644 (file)
@@ -702,7 +702,7 @@ JSObjectRef objCCallbackFunctionForBlock(JSContext *context, id target)
 
 id tryUnwrapConstructor(JSC::VM* vm, JSObjectRef object)
 {
-    if (!toJS(object)->inherits(*vm, JSC::ObjCCallbackFunction::info()))
+    if (!toJS(object)->inherits<JSC::ObjCCallbackFunction>(*vm))
         return nil;
     JSC::ObjCCallbackFunctionImpl* impl = static_cast<JSC::ObjCCallbackFunction*>(toJS(object))->impl();
     if (!impl->isConstructible())
index 603f95a..85c6bf9 100644 (file)
@@ -1,3 +1,208 @@
+2018-03-08  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [JSC] Add inherits<T>(VM&) leveraging JSCast fast path
+        https://bugs.webkit.org/show_bug.cgi?id=183429
+
+        Reviewed by Mark Lam.
+
+        Add new member function, JSCell::inherits<T>(VM&) and JSValue::inherits<T>(VM&).
+        They depends on jsDynamicCast<T> implementation and leverage JSType-based fast
+        paths defined in JSCast.h. We extract checking part as `JSCastingHelpers::inherit`
+        and construct jsDynamicCast and JSCell::inherits based on this.
+
+        And we remove several unnecessary casting functions (asRegExpObject, asDateInstance etc.).
+        In addition, we add jsDynamicCast fast path for RegExpObject by using existing RegExpObjectType.
+
+        We also fix the implementation of jsDynamicCast for JSObject since it uses LastJSCObjectType.
+        The embedder can add their extended object types after that.
+
+        * API/JSObjectRef.cpp:
+        (JSObjectGetPrivateProperty):
+        (JSObjectSetPrivateProperty):
+        (JSObjectDeletePrivateProperty):
+        * API/JSValue.mm:
+        (isDate):
+        (isArray):
+        * API/JSValueRef.cpp:
+        (JSValueIsArray):
+        (JSValueIsDate):
+        (JSValueIsObjectOfClass):
+        * API/JSWeakObjectMapRefPrivate.cpp:
+        * API/JSWrapperMap.mm:
+        (tryUnwrapObjcObject):
+        * API/ObjCCallbackFunction.mm:
+        (tryUnwrapConstructor):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGOperations.cpp:
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileOverridesHasInstance):
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewRegexp):
+        * ftl/FTLOperations.cpp:
+        (JSC::FTL::operationMaterializeObjectInOSR):
+        * inspector/JSInjectedScriptHost.cpp:
+        (Inspector::JSInjectedScriptHost::subtype):
+        (Inspector::JSInjectedScriptHost::functionDetails):
+        * inspector/agents/InspectorHeapAgent.cpp:
+        (Inspector::InspectorHeapAgent::getPreview):
+        * interpreter/Interpreter.cpp:
+        (JSC::notifyDebuggerOfUnwinding):
+        * interpreter/ShadowChicken.cpp:
+        (JSC::ShadowChicken::update):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        * jit/JITOperations.cpp:
+        (JSC::operationNewFunctionCommon):
+        * jsc.cpp:
+        (checkException):
+        * runtime/BooleanObject.h:
+        (JSC::asBooleanObject): Deleted.
+        * runtime/BooleanPrototype.cpp:
+        (JSC::booleanProtoFuncToString):
+        (JSC::booleanProtoFuncValueOf):
+        * runtime/DateConstructor.cpp:
+        (JSC::constructDate):
+        * runtime/DateInstance.h:
+        (JSC::asDateInstance): Deleted.
+        * runtime/DatePrototype.cpp:
+        (JSC::formateDateInstance):
+        (JSC::dateProtoFuncToISOString):
+        (JSC::dateProtoFuncToLocaleString):
+        (JSC::dateProtoFuncToLocaleDateString):
+        (JSC::dateProtoFuncToLocaleTimeString):
+        (JSC::dateProtoFuncGetTime):
+        (JSC::dateProtoFuncGetFullYear):
+        (JSC::dateProtoFuncGetUTCFullYear):
+        (JSC::dateProtoFuncGetMonth):
+        (JSC::dateProtoFuncGetUTCMonth):
+        (JSC::dateProtoFuncGetDate):
+        (JSC::dateProtoFuncGetUTCDate):
+        (JSC::dateProtoFuncGetDay):
+        (JSC::dateProtoFuncGetUTCDay):
+        (JSC::dateProtoFuncGetHours):
+        (JSC::dateProtoFuncGetUTCHours):
+        (JSC::dateProtoFuncGetMinutes):
+        (JSC::dateProtoFuncGetUTCMinutes):
+        (JSC::dateProtoFuncGetSeconds):
+        (JSC::dateProtoFuncGetUTCSeconds):
+        (JSC::dateProtoFuncGetMilliSeconds):
+        (JSC::dateProtoFuncGetUTCMilliseconds):
+        (JSC::dateProtoFuncGetTimezoneOffset):
+        (JSC::dateProtoFuncSetTime):
+        (JSC::setNewValueFromTimeArgs):
+        (JSC::setNewValueFromDateArgs):
+        (JSC::dateProtoFuncSetYear):
+        (JSC::dateProtoFuncGetYear):
+        * runtime/ExceptionHelpers.cpp:
+        (JSC::isTerminatedExecutionException):
+        * runtime/FunctionPrototype.cpp:
+        (JSC::functionProtoFuncToString):
+        * runtime/InternalFunction.h:
+        (JSC::asInternalFunction):
+        * runtime/JSArray.h:
+        (JSC::asArray):
+        * runtime/JSCJSValue.cpp:
+        (JSC::JSValue::dumpForBacktrace const):
+        * runtime/JSCJSValue.h:
+        * runtime/JSCJSValueInlines.h:
+        (JSC::JSValue::inherits const):
+        * runtime/JSCast.h:
+        (JSC::JSCastingHelpers::inheritsGenericImpl):
+        (JSC::JSCastingHelpers::inheritsJSTypeImpl):
+        (JSC::JSCastingHelpers::InheritsTraits::inherits):
+        (JSC::JSCastingHelpers::inherits):
+        (JSC::jsDynamicCast):
+        (JSC::JSCastingHelpers::jsDynamicCastGenericImpl): Deleted.
+        (JSC::JSCastingHelpers::jsDynamicCastJSTypeImpl): Deleted.
+        (JSC::JSCastingHelpers::JSDynamicCastTraits::cast): Deleted.
+        * runtime/JSCell.h:
+        * runtime/JSCellInlines.h:
+        (JSC::JSCell::inherits const):
+        * runtime/JSFunction.cpp:
+        (JSC::RetrieveCallerFunctionFunctor::operator() const):
+        (JSC::JSFunction::callerGetter):
+        (JSC::JSFunction::getOwnNonIndexPropertyNames):
+        (JSC::JSFunction::reifyLazyBoundNameIfNeeded):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::enqueueJob):
+        * runtime/JSGlobalObject.h:
+        (JSC::asGlobalObject): Deleted.
+        * runtime/JSInternalPromiseDeferred.cpp:
+        (JSC::JSInternalPromiseDeferred::create):
+        * runtime/JSLexicalEnvironment.h:
+        (JSC::asActivation):
+        * runtime/JSONObject.cpp:
+        (JSC::unwrapBoxedPrimitive):
+        (JSC::Stringifier::Stringifier):
+        (JSC::Walker::walk):
+        * runtime/JSPromise.cpp:
+        (JSC::JSPromise::resolve):
+        * runtime/JSPromiseDeferred.cpp:
+        (JSC::JSPromiseDeferred::create):
+        * runtime/JSType.h:
+        * runtime/ProxyObject.h:
+        (JSC::ProxyObject::create): Deleted.
+        (JSC::ProxyObject::createStructure): Deleted.
+        (JSC::ProxyObject::target const): Deleted.
+        (JSC::ProxyObject::handler const): Deleted.
+        * runtime/RegExpConstructor.cpp:
+        (JSC::constructRegExp):
+        * runtime/RegExpConstructor.h:
+        (JSC::asRegExpConstructor):
+        (JSC::isRegExp):
+        * runtime/RegExpObject.cpp:
+        (JSC::RegExpObject::finishCreation):
+        (JSC::RegExpObject::getOwnPropertySlot):
+        (JSC::RegExpObject::defineOwnProperty):
+        (JSC::regExpObjectSetLastIndexStrict):
+        (JSC::regExpObjectSetLastIndexNonStrict):
+        (JSC::RegExpObject::put):
+        * runtime/RegExpObject.h:
+        (JSC::RegExpObject::create): Deleted.
+        (JSC::RegExpObject::setRegExp): Deleted.
+        (JSC::RegExpObject::regExp const): Deleted.
+        (JSC::RegExpObject::setLastIndex): Deleted.
+        (JSC::RegExpObject::getLastIndex const): Deleted.
+        (JSC::RegExpObject::test): Deleted.
+        (JSC::RegExpObject::testInline): Deleted.
+        (JSC::RegExpObject::createStructure): Deleted.
+        (JSC::RegExpObject::offsetOfRegExp): Deleted.
+        (JSC::RegExpObject::offsetOfLastIndex): Deleted.
+        (JSC::RegExpObject::offsetOfLastIndexIsWritable): Deleted.
+        (JSC::RegExpObject::allocationSize): Deleted.
+        (JSC::asRegExpObject): Deleted.
+        * runtime/RegExpPrototype.cpp:
+        (JSC::regExpProtoFuncTestFast):
+        (JSC::regExpProtoFuncExec):
+        (JSC::regExpProtoFuncMatchFast):
+        (JSC::regExpProtoFuncCompile):
+        (JSC::regExpProtoGetterGlobal):
+        (JSC::regExpProtoGetterIgnoreCase):
+        (JSC::regExpProtoGetterMultiline):
+        (JSC::regExpProtoGetterDotAll):
+        (JSC::regExpProtoGetterSticky):
+        (JSC::regExpProtoGetterUnicode):
+        (JSC::regExpProtoGetterSource):
+        (JSC::regExpProtoFuncSearchFast):
+        (JSC::regExpProtoFuncSplitFast):
+        * runtime/StringObject.h:
+        (JSC::asStringObject): Deleted.
+        * runtime/StringPrototype.cpp:
+        (JSC::replaceUsingRegExpSearch):
+        (JSC::replace):
+        (JSC::stringProtoFuncReplaceUsingRegExp):
+        (JSC::stringProtoFuncToString):
+        * runtime/SymbolPrototype.cpp:
+        (JSC::symbolProtoFuncToString):
+        (JSC::symbolProtoFuncValueOf):
+        * tools/JSDollarVM.cpp:
+        (WTF::customGetValue):
+        (WTF::customSetValue):
+        * wasm/js/JSWebAssemblyHelpers.h:
+        (JSC::isWebAssemblyHostFunction):
+        * wasm/js/WebAssemblyWrapperFunction.cpp:
+        (JSC::WebAssemblyWrapperFunction::create):
+
 2018-03-07  Tim Horton  <timothy_horton@apple.com>
 
         Sort and separate FeatureDefines.xcconfig
index cdfb0e2..a563d78 100644 (file)
@@ -4463,7 +4463,7 @@ void ByteCodeParser::parseBlock(unsigned limit)
                 if (cachedFunction
                     && cachedFunction != JSCell::seenMultipleCalleeObjects()
                     && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
-                    ASSERT(cachedFunction->inherits(*m_vm, JSFunction::info()));
+                    ASSERT(cachedFunction->inherits<JSFunction>(*m_vm));
 
                     FrozenValue* frozen = m_graph.freeze(cachedFunction);
                     addToGraph(CheckCell, OpInfo(frozen), callee);
index 2337ac5..b1dadd2 100644 (file)
@@ -1049,7 +1049,8 @@ EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGloba
     JSValue base = JSValue::decode(encodedBase);
     JSValue argument = JSValue::decode(encodedArgument);
     
-    if (!base.inherits(vm, RegExpObject::info()))
+    auto* regexp = jsDynamicCast<RegExpObject*>(vm, base);
+    if (UNLIKELY(!regexp))
         return throwVMTypeError(exec, scope);
 
     JSString* input = argument.toStringOrNull(exec);
@@ -1057,7 +1058,7 @@ EncodedJSValue JIT_OPERATION operationRegExpExecGeneric(ExecState* exec, JSGloba
     if (!input)
         return JSValue::encode(jsUndefined());
     scope.release();
-    return JSValue::encode(asRegExpObject(base)->exec(exec, globalObject, input));
+    return JSValue::encode(regexp->exec(exec, globalObject, input));
 }
 
 EncodedJSValue JIT_OPERATION operationRegExpExecNonGlobalOrSticky(ExecState* exec, JSGlobalObject* globalObject, RegExp* regExp, JSString* string)
@@ -1180,7 +1181,8 @@ size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject*
     JSValue base = JSValue::decode(encodedBase);
     JSValue argument = JSValue::decode(encodedArgument);
 
-    if (!base.inherits(vm, RegExpObject::info())) {
+    auto* regexp = jsDynamicCast<RegExpObject*>(vm, base);
+    if (UNLIKELY(!regexp)) {
         throwTypeError(exec, scope);
         return false;
     }
@@ -1190,7 +1192,7 @@ size_t JIT_OPERATION operationRegExpTestGeneric(ExecState* exec, JSGlobalObject*
     if (!input)
         return false;
     scope.release();
-    return asRegExpObject(base)->test(exec, globalObject, input);
+    return regexp->test(exec, globalObject, input);
 }
 
 size_t JIT_OPERATION operationCompareStrictEqCell(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
index d8ebc9f..38b7471 100644 (file)
@@ -9808,7 +9808,7 @@ private:
     void compileOverridesHasInstance()
     {
         FrozenValue* defaultHasInstanceFunction = m_node->cellOperand();
-        ASSERT(defaultHasInstanceFunction->cell()->inherits(vm(), JSFunction::info()));
+        ASSERT(defaultHasInstanceFunction->cell()->inherits<JSFunction>(vm()));
 
         LValue constructor = lowCell(m_node->child1());
         LValue hasInstance = lowJSValue(m_node->child2());
@@ -10728,7 +10728,7 @@ private:
     {
         FrozenValue* regexp = m_node->cellOperand();
         LValue lastIndex = lowJSValue(m_node->child1());
-        ASSERT(regexp->cell()->inherits(vm(), RegExp::info()));
+        ASSERT(regexp->cell()->inherits<RegExp>(vm()));
         ASSERT(m_node->castOperand<RegExp*>()->isValid());
 
         LBasicBlock slowCase = m_out.newBlock();
index ac5afc4..cae8e4b 100644 (file)
@@ -150,7 +150,7 @@ extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
             if (property.location() != PromotedLocationDescriptor(StructurePLoc))
                 continue;
 
-            RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits(vm, Structure::info()));
+            RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits<Structure>(vm));
             structure = jsCast<Structure*>(JSValue::decode(values[i]));
             break;
         }
@@ -184,11 +184,11 @@ extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
         for (unsigned i = materialization->properties().size(); i--;) {
             const ExitPropertyValue& property = materialization->properties()[i];
             if (property.location() == PromotedLocationDescriptor(FunctionExecutablePLoc)) {
-                RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits(vm, FunctionExecutable::info()));
+                RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits<FunctionExecutable>(vm));
                 executable = jsCast<FunctionExecutable*>(JSValue::decode(values[i]));
             }
             if (property.location() == PromotedLocationDescriptor(FunctionActivationPLoc)) {
-                RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits(vm, JSScope::info()));
+                RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits<JSScope>(vm));
                 activation = jsCast<JSScope*>(JSValue::decode(values[i]));
             }
         }
@@ -211,10 +211,10 @@ extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
         for (unsigned i = materialization->properties().size(); i--;) {
             const ExitPropertyValue& property = materialization->properties()[i];
             if (property.location() == PromotedLocationDescriptor(ActivationScopePLoc)) {
-                RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits(vm, JSScope::info()));
+                RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits<JSScope>(vm));
                 scope = jsCast<JSScope*>(JSValue::decode(values[i]));
             } else if (property.location() == PromotedLocationDescriptor(ActivationSymbolTablePLoc)) {
-                RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits(vm, SymbolTable::info()));
+                RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits<SymbolTable>(vm));
                 table = jsCast<SymbolTable*>(JSValue::decode(values[i]));
             }
         }
@@ -552,7 +552,7 @@ extern "C" JSCell* JIT_OPERATION operationMaterializeObjectInOSR(
         for (unsigned i = materialization->properties().size(); i--;) {
             const ExitPropertyValue& property = materialization->properties()[i];
             if (property.location() == PromotedLocationDescriptor(RegExpObjectRegExpPLoc)) {
-                RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits(vm, RegExp::info()));
+                RELEASE_ASSERT(JSValue::decode(values[i]).asCell()->inherits<RegExp>(vm));
                 regExp = jsCast<RegExp*>(JSValue::decode(values[i]));
             }
         }
index e660a31..3d5c17a 100644 (file)
@@ -150,8 +150,7 @@ JSValue JSInjectedScriptHost::subtype(ExecState* exec)
     if (value.isSymbol())
         return vm.smallStrings.symbolString();
 
-    JSObject* object = asObject(value);
-    if (object) {
+    if (auto* object = jsDynamicCast<JSObject*>(vm, value)) {
         if (object->isErrorInstance())
             return jsNontrivialString(exec, ASCIILiteral("error"));
 
@@ -159,49 +158,47 @@ JSValue JSInjectedScriptHost::subtype(ExecState* exec)
         JSFunction* function = jsDynamicCast<JSFunction*>(vm, value);
         if (function && function->isClassConstructorFunction())
             return jsNontrivialString(exec, ASCIILiteral("class"));
-    }
 
-    if (value.inherits(vm, JSArray::info()))
-        return jsNontrivialString(exec, ASCIILiteral("array"));
-    if (value.inherits(vm, DirectArguments::info()) || value.inherits(vm, ScopedArguments::info()))
-        return jsNontrivialString(exec, ASCIILiteral("array"));
-
-    if (value.inherits(vm, DateInstance::info()))
-        return jsNontrivialString(exec, ASCIILiteral("date"));
-    if (value.inherits(vm, RegExpObject::info()))
-        return jsNontrivialString(exec, ASCIILiteral("regexp"));
-    if (value.inherits(vm, ProxyObject::info()))
-        return jsNontrivialString(exec, ASCIILiteral("proxy"));
-
-    if (value.inherits(vm, JSMap::info()))
-        return jsNontrivialString(exec, ASCIILiteral("map"));
-    if (value.inherits(vm, JSSet::info()))
-        return jsNontrivialString(exec, ASCIILiteral("set"));
-    if (value.inherits(vm, JSWeakMap::info()))
-        return jsNontrivialString(exec, ASCIILiteral("weakmap"));
-    if (value.inherits(vm, JSWeakSet::info()))
-        return jsNontrivialString(exec, ASCIILiteral("weakset"));
-
-    if (value.inherits(vm, JSStringIterator::info()))
-        return jsNontrivialString(exec, ASCIILiteral("iterator"));
-
-    if (object) {
+        if (object->inherits<JSArray>(vm))
+            return jsNontrivialString(exec, ASCIILiteral("array"));
+        if (object->inherits<DirectArguments>(vm) || object->inherits<ScopedArguments>(vm))
+            return jsNontrivialString(exec, ASCIILiteral("array"));
+
+        if (object->inherits<DateInstance>(vm))
+            return jsNontrivialString(exec, ASCIILiteral("date"));
+        if (object->inherits<RegExpObject>(vm))
+            return jsNontrivialString(exec, ASCIILiteral("regexp"));
+        if (object->inherits<ProxyObject>(vm))
+            return jsNontrivialString(exec, ASCIILiteral("proxy"));
+
+        if (object->inherits<JSMap>(vm))
+            return jsNontrivialString(exec, ASCIILiteral("map"));
+        if (object->inherits<JSSet>(vm))
+            return jsNontrivialString(exec, ASCIILiteral("set"));
+        if (object->inherits<JSWeakMap>(vm))
+            return jsNontrivialString(exec, ASCIILiteral("weakmap"));
+        if (object->inherits<JSWeakSet>(vm))
+            return jsNontrivialString(exec, ASCIILiteral("weakset"));
+
+        if (object->inherits<JSStringIterator>(vm))
+            return jsNontrivialString(exec, ASCIILiteral("iterator"));
+
         if (object->getDirect(vm, vm.propertyNames->builtinNames().arrayIteratorNextIndexPrivateName())
             || object->getDirect(vm, vm.propertyNames->builtinNames().mapBucketPrivateName())
             || object->getDirect(vm, vm.propertyNames->builtinNames().setBucketPrivateName()))
             return jsNontrivialString(exec, ASCIILiteral("iterator"));
-    }
 
-    if (value.inherits(vm, JSInt8Array::info())
-        || value.inherits(vm, JSInt16Array::info())
-        || value.inherits(vm, JSInt32Array::info())
-        || value.inherits(vm, JSUint8Array::info())
-        || value.inherits(vm, JSUint8ClampedArray::info())
-        || value.inherits(vm, JSUint16Array::info())
-        || value.inherits(vm, JSUint32Array::info())
-        || value.inherits(vm, JSFloat32Array::info())
-        || value.inherits(vm, JSFloat64Array::info()))
-        return jsNontrivialString(exec, ASCIILiteral("array"));
+        if (object->inherits<JSInt8Array>(vm)
+            || object->inherits<JSInt16Array>(vm)
+            || object->inherits<JSInt32Array>(vm)
+            || object->inherits<JSUint8Array>(vm)
+            || object->inherits<JSUint8ClampedArray>(vm)
+            || object->inherits<JSUint16Array>(vm)
+            || object->inherits<JSUint32Array>(vm)
+            || object->inherits<JSFloat32Array>(vm)
+            || object->inherits<JSFloat64Array>(vm))
+            return jsNontrivialString(exec, ASCIILiteral("array"));
+    }
 
     return impl().subtype(exec, value);
 }
@@ -213,14 +210,14 @@ JSValue JSInjectedScriptHost::functionDetails(ExecState* exec)
 
     VM& vm = exec->vm();
     JSValue value = exec->uncheckedArgument(0);
-    if (!value.asCell()->inherits(vm, JSFunction::info()))
+    auto* function = jsDynamicCast<JSFunction*>(vm, value);
+    if (!function)
         return jsUndefined();
 
     // FIXME: <https://webkit.org/b/87192> Web Inspector: Expose function scope / closure data
 
     // FIXME: This should provide better details for JSBoundFunctions.
 
-    JSFunction* function = jsCast<JSFunction*>(value);
     const SourceCode* sourceCode = function->sourceCode();
     if (!sourceCode)
         return jsUndefined();
index a2b6d04..2fb8b7e 100644 (file)
@@ -206,7 +206,7 @@ void InspectorHeapAgent::getPreview(ErrorString& errorString, int heapObjectId,
     }
 
     // Function preview.
-    if (cell->inherits(vm, JSFunction::info())) {
+    if (cell->inherits<JSFunction>(vm)) {
         injectedScript.functionDetails(errorString, cell, functionDetails);
         return;
     }
index cdc0f72..ea78ac6 100644 (file)
@@ -631,7 +631,7 @@ ALWAYS_INLINE static void notifyDebuggerOfUnwinding(VM& vm, CallFrame* callFrame
     if (Debugger* debugger = callFrame->vmEntryGlobalObject(vm)->debugger()) {
         SuspendExceptionScope scope(&vm);
         if (callFrame->isAnyWasmCallee()
-            || (callFrame->callee().isCell() && callFrame->callee().asCell()->inherits(vm, JSFunction::info())))
+            || (callFrame->callee().isCell() && callFrame->callee().asCell()->inherits<JSFunction>(vm)))
             debugger->unwindEvent(callFrame);
         else
             debugger->didExecuteProgram(callFrame);
index f70666d..e3443f1 100644 (file)
@@ -302,11 +302,11 @@ void ShadowChicken::update(VM& vm, ExecState* exec)
             CodeBlock* codeBlock = callFrame->codeBlock();
             if (codeBlock && codeBlock->wasCompiledWithDebuggingOpcodes() && codeBlock->scopeRegister().isValid()) {
                 scope = callFrame->scope(codeBlock->scopeRegister().offset());
-                RELEASE_ASSERT(scope->inherits(vm, JSScope::info()));
+                RELEASE_ASSERT(scope->inherits<JSScope>(vm));
             } else if (foundFrame) {
                 scope = m_log[indexInLog].scope;
                 if (scope)
-                    RELEASE_ASSERT(scope->inherits(vm, JSScope::info()));
+                    RELEASE_ASSERT(scope->inherits<JSScope>(vm));
             }
             toPush.append(Frame(jsCast<JSObject*>(visitor->callee().asCell()), callFrame, isTailDeleted, callFrame->thisValue(), scope, codeBlock, callFrame->callSiteIndex()));
 
@@ -351,7 +351,7 @@ void ShadowChicken::update(VM& vm, ExecState* exec)
                     }
                     Packet packet = m_log[indexInLog];
                     bool isTailDeleted = true;
-                    RELEASE_ASSERT(tailPacket.scope->inherits(vm, JSScope::info()));
+                    RELEASE_ASSERT(tailPacket.scope->inherits<JSScope>(vm));
                     toPush.append(Frame(packet.callee, packet.frame, isTailDeleted, tailPacket.thisValue, tailPacket.scope, tailPacket.codeBlock, tailPacket.callSiteIndex));
                 }
             }
index f6420ca..551139f 100644 (file)
@@ -196,7 +196,7 @@ void JIT::privateCompileMainPass()
 
     VM& vm = *m_codeBlock->vm();
     unsigned startBytecodeOffset = 0;
-    if (m_loopOSREntryBytecodeOffset && (m_codeBlock->inherits(vm, ProgramCodeBlock::info()) || m_codeBlock->inherits(vm, ModuleProgramCodeBlock::info()))) {
+    if (m_loopOSREntryBytecodeOffset && (m_codeBlock->inherits<ProgramCodeBlock>(vm) || m_codeBlock->inherits<ModuleProgramCodeBlock>(vm))) {
         // We can only do this optimization because we execute ProgramCodeBlock's exactly once.
         // This optimization would be invalid otherwise. When the LLInt determines it wants to
         // do OSR entry into the baseline JIT in a loop, it will pass in the bytecode offset it
index 9dc544e..e46a3d7 100644 (file)
@@ -1191,7 +1191,7 @@ template<typename FunctionType>
 static EncodedJSValue operationNewFunctionCommon(ExecState* exec, JSScope* scope, JSCell* functionExecutable, bool isInvalidated)
 {
     VM& vm = exec->vm();
-    ASSERT(functionExecutable->inherits(vm, FunctionExecutable::info()));
+    ASSERT(functionExecutable->inherits<FunctionExecutable>(vm));
     NativeCallFrameTracer tracer(&vm, exec);
     if (isInvalidated)
         return JSValue::encode(FunctionType::createWithInvalidatedReallocationWatchpoint(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
index 9ef84aa..ef92c42 100644 (file)
@@ -2263,7 +2263,7 @@ static void checkException(GlobalObject* globalObject, bool isLastFile, bool has
 {
     VM& vm = globalObject->vm();
 
-    if (options.m_treatWatchdogExceptionAsSuccess && value.inherits(vm, TerminatedExecutionError::info())) {
+    if (options.m_treatWatchdogExceptionAsSuccess && value.inherits<TerminatedExecutionError>(vm)) {
         ASSERT(hasException);
         return;
     }
index 9e5aaf9..27c43e7 100644 (file)
@@ -47,12 +47,4 @@ public:
     }
 };
 
-BooleanObject* asBooleanObject(JSValue);
-
-inline BooleanObject* asBooleanObject(JSValue value)
-{
-    ASSERT(asObject(value)->inherits(*value.getObject()->vm(), BooleanObject::info()));
-    return static_cast<BooleanObject*>(asObject(value));
-}
-
 } // namespace JSC
index 37dce7e..06f9fd3 100644 (file)
@@ -76,13 +76,14 @@ EncodedJSValue JSC_HOST_CALL booleanProtoFuncToString(ExecState* exec)
     if (thisValue == jsBoolean(true))
         return JSValue::encode(vm.smallStrings.trueString());
 
-    if (!thisValue.inherits(vm, BooleanObject::info()))
+    auto* thisObject = jsDynamicCast<BooleanObject*>(vm, thisValue);
+    if (UNLIKELY(!thisObject))
         return throwVMTypeError(exec, scope);
 
-    if (asBooleanObject(thisValue)->internalValue() == jsBoolean(false))
+    if (thisObject->internalValue() == jsBoolean(false))
         return JSValue::encode(vm.smallStrings.falseString());
 
-    ASSERT(asBooleanObject(thisValue)->internalValue() == jsBoolean(true));
+    ASSERT(thisObject->internalValue() == jsBoolean(true));
     return JSValue::encode(vm.smallStrings.trueString());
 }
 
@@ -94,10 +95,11 @@ EncodedJSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState* exec)
     if (thisValue.isBoolean())
         return JSValue::encode(thisValue);
 
-    if (!thisValue.inherits(vm, BooleanObject::info()))
+    auto* thisObject = jsDynamicCast<BooleanObject*>(vm, thisValue);
+    if (UNLIKELY(!thisObject))
         return throwVMTypeError(exec, scope);
 
-    return JSValue::encode(asBooleanObject(thisValue)->internalValue());
+    return JSValue::encode(thisObject->internalValue());
 }
 
 } // namespace JSC
index 61a5952..003fa90 100644 (file)
@@ -130,10 +130,11 @@ JSObject* constructDate(ExecState* exec, JSGlobalObject* globalObject, JSValue n
     if (numArgs == 0) // new Date() ECMA 15.9.3.3
         value = jsCurrentTime();
     else if (numArgs == 1) {
-        if (args.at(0).inherits(vm, DateInstance::info()))
-            value = asDateInstance(args.at(0))->internalNumber();
+        JSValue arg0 = args.at(0);
+        if (auto* dateInstance = jsDynamicCast<DateInstance*>(vm, arg0))
+            value = dateInstance->internalNumber();
         else {
-            JSValue primitive = args.at(0).toPrimitive(exec);
+            JSValue primitive = arg0.toPrimitive(exec);
             RETURN_IF_EXCEPTION(scope, nullptr);
             if (primitive.isString())
                 value = parseDate(vm, asString(primitive)->value(exec));
index 3f11ae3..5784135 100644 (file)
@@ -80,12 +80,4 @@ private:
     mutable PoisonedRefPtr<DateInstancePoison, DateInstanceData> m_data;
 };
 
-DateInstance* asDateInstance(JSValue);
-
-inline DateInstance* asDateInstance(JSValue value)
-{
-    ASSERT(asObject(value)->inherits(*value.getObject()->vm(), DateInstance::info()));
-    return static_cast<DateInstance*>(asObject(value));
-}
-
 } // namespace JSC
index 5ab007f..6f23368 100644 (file)
@@ -322,11 +322,10 @@ static EncodedJSValue formateDateInstance(ExecState* exec, DateTimeFormat format
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue);
-
     const GregorianDateTime* gregorianDateTime = asUTCVariant
         ? thisDateObj->gregorianDateTimeUTC(exec)
         : thisDateObj->gregorianDateTime(exec);
@@ -539,10 +538,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
     
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     if (!std::isfinite(thisDateObj->internalNumber()))
         return throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("Invalid Date")));
 
@@ -587,10 +586,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDateAndTime));
 }
 
@@ -599,10 +598,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDate));
 }
 
@@ -611,10 +610,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     return JSValue::encode(formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleTime));
 }
 
@@ -646,10 +645,11 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    return JSValue::encode(asDateInstance(thisValue)->internalValue());
+    return JSValue::encode(thisDateObj->internalValue());
 }
 
 EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec)
@@ -657,11 +657,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -673,11 +672,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -689,11 +687,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -705,11 +702,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -721,11 +717,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -737,11 +732,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -753,11 +747,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -769,11 +762,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -785,11 +777,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -801,11 +792,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -817,11 +807,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -833,11 +822,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -849,11 +837,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -865,11 +852,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -881,10 +867,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     double milli = thisDateObj->internalNumber();
     if (std::isnan(milli))
         return JSValue::encode(jsNaN());
@@ -899,10 +885,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetUTCMilliseconds(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
     double milli = thisDateObj->internalNumber();
     if (std::isnan(milli))
         return JSValue::encode(jsNaN());
@@ -917,11 +903,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
@@ -933,11 +918,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     double milli = timeClip(exec->argument(0).toNumber(exec));
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
     JSValue result = jsNumber(milli);
@@ -950,10 +934,10 @@ static EncodedJSValue setNewValueFromTimeArgs(ExecState* exec, int numArgsToUse,
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue);
     double milli = thisDateObj->internalNumber();
 
     if (!exec->argumentCount() || std::isnan(milli)) {
@@ -992,10 +976,10 @@ static EncodedJSValue setNewValueFromDateArgs(ExecState* exec, int numArgsToUse,
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue);
     if (!exec->argumentCount()) {
         JSValue result = jsNaN();
         thisDateObj->setInternalValue(vm, result);
@@ -1107,10 +1091,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue);
     if (!exec->argumentCount()) { 
         JSValue result = jsNaN();
         thisDateObj->setInternalValue(vm, result);
@@ -1152,11 +1136,10 @@ EncodedJSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, DateInstance::info()))
+    auto* thisDateObj = jsDynamicCast<DateInstance*>(vm, thisValue);
+    if (UNLIKELY(!thisDateObj))
         return throwVMTypeError(exec, scope);
 
-    DateInstance* thisDateObj = asDateInstance(thisValue); 
-
     const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec);
     if (!gregorianDateTime)
         return JSValue::encode(jsNaN());
index 98268e5..699144b 100644 (file)
@@ -65,7 +65,7 @@ bool isTerminatedExecutionException(VM& vm, Exception* exception)
     if (!exception->value().isObject())
         return false;
 
-    return exception->value().inherits(vm, TerminatedExecutionError::info());
+    return exception->value().inherits<TerminatedExecutionError>(vm);
 }
 
 JSObject* createStackOverflowError(ExecState* exec)
index e04313f..d0fd762 100644 (file)
@@ -85,7 +85,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue thisValue = exec->thisValue();
-    if (thisValue.inherits(vm, JSFunction::info())) {
+    if (thisValue.inherits<JSFunction>(vm)) {
         JSFunction* function = jsCast<JSFunction*>(thisValue);
         if (function->isHostOrBuiltinFunction()) {
             scope.release();
@@ -98,7 +98,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
             return JSValue::encode(jsString(exec, classSource.toStringWithoutCopying()));
         }
 
-        if (thisValue.inherits(vm, JSAsyncFunction::info())) {
+        if (thisValue.inherits<JSAsyncFunction>(vm)) {
             String functionHeader = executable->isArrowFunction() ? "async " : "async function ";
 
             StringView source = executable->source().provider()->getRange(
@@ -116,7 +116,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec)
         return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source));
     }
 
-    if (thisValue.inherits(vm, InternalFunction::info())) {
+    if (thisValue.inherits<InternalFunction>(vm)) {
         InternalFunction* function = asInternalFunction(thisValue);
         scope.release();
         return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(), "() {\n    [native code]\n}"));
index 2d9bb50..7b7c8ba 100644 (file)
@@ -91,7 +91,7 @@ InternalFunction* asInternalFunction(JSValue);
 
 inline InternalFunction* asInternalFunction(JSValue value)
 {
-    ASSERT(asObject(value)->inherits(*value.getObject()->vm(), InternalFunction::info()));
+    ASSERT(asObject(value)->inherits<InternalFunction>(*value.getObject()->vm()));
     return static_cast<InternalFunction*>(asObject(value));
 }
 
index 8772aa2..7150bbf 100644 (file)
@@ -289,7 +289,7 @@ JSArray* asArray(JSValue);
 
 inline JSArray* asArray(JSCell* cell)
 {
-    ASSERT(cell->inherits(*cell->vm(), JSArray::info()));
+    ASSERT(cell->inherits<JSArray>(*cell->vm()));
     return jsCast<JSArray*>(cell);
 }
 
index 115d8b3..b5f77be 100644 (file)
@@ -309,14 +309,14 @@ void JSValue::dumpForBacktrace(PrintStream& out) const
         out.printf("%lf", asDouble());
     else if (isCell()) {
         VM& vm = *asCell()->vm();
-        if (asCell()->inherits(vm, JSString::info())) {
+        if (asCell()->inherits<JSString>(vm)) {
             JSString* string = asString(asCell());
             const StringImpl* impl = string->tryGetValueImpl();
             if (impl)
                 out.print("\"", impl, "\"");
             else
                 out.print("(unresolved string)");
-        } else if (asCell()->inherits(vm, Structure::info())) {
+        } else if (asCell()->inherits<Structure>(vm)) {
             out.print("Structure[ ", asCell()->structure()->classInfo()->className);
 #if USE(JSVALUE64)
             out.print(" ID: ", asCell()->structureID());
index 1a4497e..366b0a2 100644 (file)
@@ -236,6 +236,7 @@ public:
     bool isCustomGetterSetter() const;
     bool isObject() const;
     bool inherits(VM&, const ClassInfo*) const;
+    template<typename Target> bool inherits(VM&) const;
     const ClassInfo* classInfoOrNull(VM&) const;
         
     // Extracting the value.
index aa51dd5..b5a4b4b 100644 (file)
@@ -785,6 +785,12 @@ inline bool JSValue::inherits(VM& vm, const ClassInfo* classInfo) const
     return isCell() && asCell()->inherits(vm, classInfo);
 }
 
+template<typename Target>
+inline bool JSValue::inherits(VM& vm) const
+{
+    return isCell() && asCell()->inherits<Target>(vm);
+}
+
 inline const ClassInfo* JSValue::classInfoOrNull(VM& vm) const
 {
     return isCell() ? asCell()->classInfo(vm) : nullptr;
index 1857f68..9285a1b 100644 (file)
@@ -47,7 +47,7 @@ inline To jsCast(JSValue from)
 
 // Specific type overloads.
 #define FOR_EACH_JS_DYNAMIC_CAST_JS_TYPE_OVERLOAD(macro) \
-    macro(JSObject, JSType::ObjectType, JSType::LastJSCObjectType) \
+    macro(JSObject, FirstObjectType, LastObjectType) \
     macro(JSFinalObject, JSType::FinalObjectType, JSType::FinalObjectType) \
     macro(JSFunction, JSType::JSFunctionType, JSType::JSFunctionType) \
     macro(InternalFunction, JSType::InternalFunctionType, JSType::InternalFunctionType) \
@@ -59,6 +59,7 @@ inline To jsCast(JSValue from)
     macro(JSWeakMap, JSType::JSWeakMapType, JSType::JSWeakMapType) \
     macro(NumberObject, JSType::NumberObjectType, JSType::NumberObjectType) \
     macro(ProxyObject, JSType::ProxyObjectType, JSType::ProxyObjectType) \
+    macro(RegExpObject, JSType::RegExpObjectType, JSType::RegExpObjectType) \
     macro(DirectArguments, JSType::DirectArgumentsType, JSType::DirectArgumentsType) \
     macro(ScopedArguments, JSType::ScopedArgumentsType, JSType::ScopedArgumentsType) \
     macro(ClonedArguments, JSType::ClonedArgumentsType, JSType::ClonedArgumentsType) \
@@ -78,52 +79,60 @@ FOR_EACH_JS_DYNAMIC_CAST_JS_TYPE_OVERLOAD(FORWARD_DECLARE_OVERLOAD_CLASS)
 
 namespace JSCastingHelpers {
 
-template<typename To, typename From>
-inline To jsDynamicCastGenericImpl(VM& vm, From* from)
+template<typename Target, typename From>
+inline bool inheritsGenericImpl(VM& vm, From* from)
 {
-    static_assert(!std::is_same<JSObject*, To*>::value, "This ensures our overloads work");
-    static_assert(std::is_base_of<JSCell, typename std::remove_pointer<To>::type>::value && std::is_base_of<JSCell, typename std::remove_pointer<From>::type>::value, "JS casting expects that the types you are casting to/from are subclasses of JSCell");
-    if (LIKELY(from->JSCell::inherits(vm, std::remove_pointer<To>::type::info())))
-        return static_cast<To>(from);
-    return nullptr;
+    static_assert(!std::is_same<JSObject*, Target*>::value, "This ensures our overloads work");
+    static_assert(std::is_base_of<JSCell, Target>::value && std::is_base_of<JSCell, typename std::remove_pointer<From>::type>::value, "JS casting expects that the types you are casting to/from are subclasses of JSCell");
+    // Do not use inherits<Target>(vm) since inherits<T> depends on this function.
+    return from->JSCell::inherits(vm, Target::info());
 }
 
-template<typename To, typename From>
-inline To jsDynamicCastJSTypeImpl(VM& vm, From* from, JSType firstType, JSType lastType)
+template<typename Target, typename From>
+inline bool inheritsJSTypeImpl(VM& vm, From* from, JSType firstType, JSType lastType)
 {
+    static_assert(std::is_base_of<JSCell, Target>::value && std::is_base_of<JSCell, typename std::remove_pointer<From>::type>::value, "JS casting expects that the types you are casting to/from are subclasses of JSCell");
     bool canCast = firstType <= from->type() && from->type() <= lastType;
-    ASSERT_UNUSED(vm, canCast == jsDynamicCastGenericImpl<To>(vm, from));
-    if (LIKELY(canCast))
-        return static_cast<To>(from);
-    return nullptr;
+    ASSERT_UNUSED(vm, canCast == from->JSCell::inherits(vm, Target::info()));
+    return canCast;
 }
 
 // C++ has bad syntax so we need to use this struct because C++ doesn't have a
 // way to say that we are overloading just the first type in a template list...
-template<typename to>
-struct JSDynamicCastTraits {
-    template<typename To, typename From>
-    static inline To cast(VM& vm, From* from) { return jsDynamicCastGenericImpl<To>(vm, from); }
+template<typename Target>
+struct InheritsTraits {
+    template<typename From>
+    static inline bool inherits(VM& vm, From* from) { return inheritsGenericImpl<Target>(vm, from); }
 };
 
 #define DEFINE_TRAITS_FOR_JS_TYPE_OVERLOAD(className, firstJSType, lastJSType) \
     template<> \
-    struct JSDynamicCastTraits<className*> { \
-        template<typename To, typename From> \
-        static inline To cast(VM& vm, From* from) { return jsDynamicCastJSTypeImpl<To>(vm, from, firstJSType, lastJSType); } \
+    struct InheritsTraits<className> { \
+        template<typename From> \
+        static inline bool inherits(VM& vm, From* from) { return inheritsJSTypeImpl<className, From>(vm, from, static_cast<JSType>(firstJSType), static_cast<JSType>(lastJSType)); } \
     }; \
 
 FOR_EACH_JS_DYNAMIC_CAST_JS_TYPE_OVERLOAD(DEFINE_TRAITS_FOR_JS_TYPE_OVERLOAD)
 
 #undef DEFINE_TRAITS_FOR_JS_TYPE_OVERLOAD
 
+
+template<typename Target, typename From>
+bool inherits(VM& vm, From* from)
+{
+    using Dispatcher = InheritsTraits<Target>;
+    return Dispatcher::template inherits(vm, from);
+}
+
 } // namespace JSCastingHelpers
 
 template<typename To, typename From>
 To jsDynamicCast(VM& vm, From* from)
 {
-    typedef JSCastingHelpers::JSDynamicCastTraits<typename std::remove_cv<typename std::remove_pointer<To>::type>::type> Dispatcher;
-    return Dispatcher::template cast<To>(vm, from);
+    using Dispatcher = JSCastingHelpers::InheritsTraits<typename std::remove_cv<typename std::remove_pointer<To>::type>::type>;
+    if (LIKELY(Dispatcher::template inherits(vm, from)))
+        return static_cast<To>(from);
+    return nullptr;
 }
 
 template<typename To>
index cadcf77..de0aaa9 100644 (file)
@@ -116,6 +116,7 @@ public:
     bool isCustomGetterSetter() const;
     bool isProxy() const;
     bool inherits(VM&, const ClassInfo*) const;
+    template<typename Target> bool inherits(VM&) const;
     bool isAPIValueWrapper() const;
     
     // Each cell has a built-in lock. Currently it's simply available for use if you need it. It's
index ccff6bd..f6cb1cd 100644 (file)
@@ -265,6 +265,12 @@ inline bool JSCell::inherits(VM& vm, const ClassInfo* info) const
     return classInfo(vm)->isSubClassOf(info);
 }
 
+template<typename Target>
+inline bool JSCell::inherits(VM& vm) const
+{
+    return JSCastingHelpers::inherits<Target>(vm, this);
+}
+
 ALWAYS_INLINE JSValue JSCell::fastGetOwnProperty(VM& vm, Structure& structure, PropertyName name)
 {
     ASSERT(canUseFastGetOwnProperty(structure));
index 04c8b22..bea921e 100644 (file)
@@ -312,7 +312,7 @@ public:
 
         JSCell* callee = visitor->callee().asCell();
 
-        if (callee && callee->inherits(*callee->vm(), JSBoundFunction::info()))
+        if (callee && callee->inherits<JSBoundFunction>(*callee->vm()))
             return StackVisitor::Continue;
 
         if (!m_hasFoundFrame && (callee != m_targetCallee))
@@ -353,7 +353,7 @@ EncodedJSValue JSFunction::callerGetter(ExecState* exec, EncodedJSValue thisValu
     JSValue caller = retrieveCallerFunction(exec, thisObj);
 
     // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller.
-    if (!caller.isObject() || !asObject(caller)->inherits(vm, JSFunction::info())) {
+    if (!caller.isObject() || !asObject(caller)->inherits<JSFunction>(vm)) {
         // It isn't a JSFunction, but if it is a JSCallee from a program or eval call or an internal constructor, return null.
         if (jsDynamicCast<JSCallee*>(vm, caller) || jsDynamicCast<InternalFunction*>(vm, caller))
             return JSValue::encode(jsNull());
@@ -451,7 +451,7 @@ void JSFunction::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec,
         } else {
             if (thisObject->isBuiltinFunction() && !thisObject->hasReifiedLength())
                 propertyNames.add(vm.propertyNames->length);
-            if ((thisObject->isBuiltinFunction() || thisObject->inherits(vm, JSBoundFunction::info())) && !thisObject->hasReifiedName())
+            if ((thisObject->isBuiltinFunction() || thisObject->inherits<JSBoundFunction>(vm)) && !thisObject->hasReifiedName())
                 propertyNames.add(vm.propertyNames->name);
         }
     }
@@ -752,7 +752,7 @@ JSFunction::PropertyStatus JSFunction::reifyLazyBoundNameIfNeeded(VM& vm, ExecSt
 
     if (isBuiltinFunction())
         reifyName(vm, exec);
-    else if (this->inherits(vm, JSBoundFunction::info())) {
+    else if (this->inherits<JSBoundFunction>(vm)) {
         FunctionRareData* rareData = this->rareData(vm);
         String name = makeString("bound ", static_cast<NativeExecutable*>(m_executable.get())->name());
         unsigned initialAttributes = PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly;
index 461e003..01e1bcb 100644 (file)
@@ -327,7 +327,7 @@ static EncodedJSValue JSC_HOST_CALL enqueueJob(ExecState* exec)
 
     JSValue job = exec->argument(0);
     JSValue arguments = exec->argument(1);
-    ASSERT(arguments.inherits(vm, JSArray::info()));
+    ASSERT(arguments.inherits<JSArray>(vm));
 
     globalObject->queueMicrotask(createJSJob(vm, job, jsCast<JSArray*>(arguments)));
 
index cefe6d5..6ab7023 100644 (file)
@@ -925,14 +925,6 @@ private:
     RefPtr<ThreadLocalCache> m_threadLocalCache;
 };
 
-JSGlobalObject* asGlobalObject(JSValue);
-
-inline JSGlobalObject* asGlobalObject(JSValue value)
-{
-    ASSERT(asObject(value)->isGlobalObject());
-    return jsCast<JSGlobalObject*>(asObject(value));
-}
-
 inline JSArray* constructEmptyArray(ExecState* exec, ArrayAllocationProfile* profile, JSGlobalObject* globalObject, unsigned initialLength = 0, JSValue newTarget = JSValue())
 {
     VM& vm = globalObject->vm();
index 179ba76..449cc9e 100644 (file)
@@ -47,7 +47,7 @@ JSInternalPromiseDeferred* JSInternalPromiseDeferred::create(ExecState* exec, JS
 
     JSValue promise = deferred.get(exec, vm.propertyNames->builtinNames().promisePrivateName());
     RETURN_IF_EXCEPTION(scope, nullptr);
-    ASSERT(promise.inherits(vm, JSInternalPromise::info()));
+    ASSERT(promise.inherits<JSInternalPromise>(vm));
     JSValue resolve = deferred.get(exec, vm.propertyNames->builtinNames().resolvePrivateName());
     RETURN_IF_EXCEPTION(scope, nullptr);
     JSValue reject = deferred.get(exec, vm.propertyNames->builtinNames().rejectPrivateName());
index ee015e2..fd3e4e0 100644 (file)
@@ -145,7 +145,7 @@ inline JSLexicalEnvironment::JSLexicalEnvironment(VM& vm, Structure* structure,
 
 inline JSLexicalEnvironment* asActivation(JSValue value)
 {
-    ASSERT(asObject(value)->inherits(*value.getObject()->vm(), JSLexicalEnvironment::info()));
+    ASSERT(asObject(value)->inherits<JSLexicalEnvironment>(*value.getObject()->vm()));
     return jsCast<JSLexicalEnvironment*>(asObject(value));
 }
     
index ecdbd03..b38d88c 100644 (file)
@@ -143,11 +143,11 @@ static inline JSValue unwrapBoxedPrimitive(ExecState* exec, JSValue value)
     if (!value.isObject())
         return value;
     JSObject* object = asObject(value);
-    if (object->inherits(vm, NumberObject::info()))
+    if (object->inherits<NumberObject>(vm))
         return jsNumber(object->toNumber(exec));
-    if (object->inherits(vm, StringObject::info()))
+    if (object->inherits<StringObject>(vm))
         return object->toString(exec);
-    if (object->inherits(vm, BooleanObject::info()))
+    if (object->inherits<BooleanObject>(vm))
         return object->toPrimitive(exec);
 
     // Do not unwrap SymbolObject to Symbol. It is not performed in the spec.
@@ -235,7 +235,7 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
         return;
 
     JSObject* replacerObject = asObject(m_replacer);
-    if (replacerObject->inherits(vm, JSArray::info())) {
+    if (replacerObject->inherits<JSArray>(vm)) {
         m_usingArrayReplacer = true;
         JSArray* array = jsCast<JSArray*>(replacerObject);
         unsigned length = array->get(exec, vm.propertyNames->length).toUInt32(exec);
@@ -246,8 +246,8 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space)
             if (UNLIKELY(scope.exception()))
                 break;
 
-            if (name.isObject()) {
-                if (!asObject(name)->inherits(vm, NumberObject::info()) && !asObject(name)->inherits(vm, StringObject::info()))
+            if (auto* nameObject = jsDynamicCast<JSObject*>(vm, name)) {
+                if (!nameObject->inherits<NumberObject>(vm) && !nameObject->inherits<StringObject>(vm))
                     continue;
             } else if (!name.isNumber() && !name.isString())
                 continue;
@@ -649,7 +649,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             arrayStartState:
             case ArrayStartState: {
                 ASSERT(inValue.isObject());
-                ASSERT(isJSArray(asObject(inValue)) || asObject(inValue)->inherits(vm, JSArray::info()));
+                ASSERT(asObject(inValue)->inherits<JSArray>(vm));
                 if (markedStack.size() > maximumFilterRecursion)
                     return throwStackOverflowError(m_exec, scope);
 
@@ -704,7 +704,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
             objectStartState:
             case ObjectStartState: {
                 ASSERT(inValue.isObject());
-                ASSERT(!isJSArray(asObject(inValue)) && !asObject(inValue)->inherits(vm, JSArray::info()));
+                ASSERT(!asObject(inValue)->inherits<JSArray>(vm));
                 if (markedStack.size() > maximumFilterRecursion)
                     return throwStackOverflowError(m_exec, scope);
 
@@ -765,7 +765,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered)
                     break;
                 }
                 JSObject* object = asObject(inValue);
-                if (isJSArray(object) || object->inherits(vm, JSArray::info()))
+                if (object->inherits<JSArray>(vm))
                     goto arrayStartState;
                 goto objectStartState;
         }
index f96fea1..3e6887e 100644 (file)
@@ -109,7 +109,7 @@ JSPromise* JSPromise::resolve(JSGlobalObject& globalObject, JSValue value)
     ASSERT(!arguments.hasOverflowed());
     auto result = call(exec, promiseResolveFunction, callType, callData, globalObject.promiseConstructor(), arguments);
     RETURN_IF_EXCEPTION(scope, nullptr);
-    ASSERT(result.inherits(vm, JSPromise::info()));
+    ASSERT(result.inherits<JSPromise>(vm));
     return jsCast<JSPromise*>(result);
 }
 
index baa9924..d7f7d78 100644 (file)
@@ -63,7 +63,7 @@ JSPromiseDeferred* JSPromiseDeferred::create(ExecState* exec, JSGlobalObject* gl
 
     JSValue promise = deferred.get(exec, vm.propertyNames->builtinNames().promisePrivateName());
     RETURN_IF_EXCEPTION(scope, nullptr);
-    ASSERT(promise.inherits(vm, JSPromise::info()));
+    ASSERT(promise.inherits<JSPromise>(vm));
     JSValue resolve = deferred.get(exec, vm.propertyNames->builtinNames().resolvePrivateName());
     RETURN_IF_EXCEPTION(scope, nullptr);
     JSValue reject = deferred.get(exec, vm.propertyNames->builtinNames().rejectPrivateName());
index b3f7cd2..88b7815 100644 (file)
@@ -111,12 +111,17 @@ enum JSType : uint8_t {
     WebAssemblyFunctionType,
     WebAssemblyToJSCalleeType,
 
-    LastJSCObjectType = WebAssemblyToJSCalleeType,
+    LastJSCObjectType = WebAssemblyToJSCalleeType, // This is the last "JSC" Object type. After this, we have embedder's (e.g., WebCore) extended object types.
     MaxJSType = 0b11111111,
 };
 
 static const uint32_t FirstTypedArrayType = Int8ArrayType;
 static const uint32_t LastTypedArrayType = DataViewType;
+
+// LastObjectType should be MaxJSType (not LastJSCObjectType) since embedders can add their extended object types after the enums listed in JSType.
+static const uint32_t FirstObjectType = ObjectType;
+static const uint32_t LastObjectType = MaxJSType;
+
 static constexpr uint32_t NumberOfTypedArrayTypes = LastTypedArrayType - FirstTypedArrayType + 1;
 static constexpr uint32_t NumberOfTypedArrayTypesExcludingDataView = NumberOfTypedArrayTypes - 1;
 
index 2c98163..ebb1fa2 100644 (file)
@@ -30,7 +30,7 @@
 
 namespace JSC {
 
-class ProxyObject : public JSNonFinalObject {
+class ProxyObject final : public JSNonFinalObject {
 public:
     typedef JSNonFinalObject Base;
 
index 0f52aa2..5068572 100644 (file)
@@ -257,7 +257,7 @@ JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const A
     JSValue patternArg = args.at(0);
     JSValue flagsArg = args.at(1);
 
-    bool isPatternRegExp = patternArg.inherits(vm, RegExpObject::info());
+    bool isPatternRegExp = patternArg.inherits<RegExpObject>(vm);
     bool constructAsRegexp = isRegExp(vm, exec, patternArg);
     RETURN_IF_EXCEPTION(scope, nullptr);
 
index da760ec..0168e58 100644 (file)
@@ -86,7 +86,7 @@ JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&, JSObject*
 
 inline RegExpConstructor* asRegExpConstructor(JSValue value)
 {
-    ASSERT(asObject(value)->inherits(*value.getObject()->vm(), RegExpConstructor::info()));
+    ASSERT(asObject(value)->inherits<RegExpConstructor>(*value.getObject()->vm()));
     return static_cast<RegExpConstructor*>(asObject(value));
 }
 
@@ -140,7 +140,7 @@ ALWAYS_INLINE bool isRegExp(VM& vm, ExecState* exec, JSValue value)
     if (!matchValue.isUndefined())
         return matchValue.toBoolean(exec);
 
-    return object->inherits(vm, RegExpObject::info());
+    return object->inherits<RegExpObject>(vm);
 }
 
 EncodedJSValue JSC_HOST_CALL esSpecRegExpCreate(ExecState*);
index 425249c..9a46629 100644 (file)
@@ -49,6 +49,7 @@ void RegExpObject::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
     ASSERT(inherits(vm, info()));
+    ASSERT(type() == RegExpObjectType);
 }
 
 void RegExpObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
@@ -64,7 +65,7 @@ bool RegExpObject::getOwnPropertySlot(JSObject* object, ExecState* exec, Propert
 {
     VM& vm = exec->vm();
     if (propertyName == vm.propertyNames->lastIndex) {
-        RegExpObject* regExp = asRegExpObject(object);
+        RegExpObject* regExp = jsCast<RegExpObject*>(object);
         unsigned attributes = regExp->m_lastIndexIsWritable ? PropertyAttribute::DontDelete | PropertyAttribute::DontEnum : PropertyAttribute::DontDelete | PropertyAttribute::DontEnum | PropertyAttribute::ReadOnly;
         slot.setValue(regExp, attributes, regExp->getLastIndex());
         return true;
@@ -110,7 +111,7 @@ bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, Property
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     if (propertyName == vm.propertyNames->lastIndex) {
-        RegExpObject* regExp = asRegExpObject(object);
+        RegExpObject* regExp = jsCast<RegExpObject*>(object);
         if (descriptor.configurablePresent() && descriptor.configurable())
             return typeError(exec, scope, shouldThrow, ASCIILiteral(UnconfigurablePropertyChangeConfigurabilityError));
         if (descriptor.enumerablePresent() && descriptor.enumerable())
@@ -139,12 +140,12 @@ bool RegExpObject::defineOwnProperty(JSObject* object, ExecState* exec, Property
 
 static bool regExpObjectSetLastIndexStrict(ExecState* exec, EncodedJSValue thisValue, EncodedJSValue value)
 {
-    return asRegExpObject(JSValue::decode(thisValue))->setLastIndex(exec, JSValue::decode(value), true);
+    return jsCast<RegExpObject*>(JSValue::decode(thisValue))->setLastIndex(exec, JSValue::decode(value), true);
 }
 
 static bool regExpObjectSetLastIndexNonStrict(ExecState* exec, EncodedJSValue thisValue, EncodedJSValue value)
 {
-    return asRegExpObject(JSValue::decode(thisValue))->setLastIndex(exec, JSValue::decode(value), false);
+    return jsCast<RegExpObject*>(JSValue::decode(thisValue))->setLastIndex(exec, JSValue::decode(value), false);
 }
 
 bool RegExpObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
@@ -156,8 +157,8 @@ bool RegExpObject::put(JSCell* cell, ExecState* exec, PropertyName propertyName,
         return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
 
     if (propertyName == vm.propertyNames->lastIndex) {
-        bool result = asRegExpObject(cell)->setLastIndex(exec, value, slot.isStrictMode());
-        slot.setCustomValue(asRegExpObject(cell), slot.isStrictMode()
+        bool result = thisObject->setLastIndex(exec, value, slot.isStrictMode());
+        slot.setCustomValue(thisObject, slot.isStrictMode()
             ? regExpObjectSetLastIndexStrict
             : regExpObjectSetLastIndexNonStrict);
         return result;
index da79090..4f7ab53 100644 (file)
@@ -27,9 +27,9 @@
 
 namespace JSC {
     
-class RegExpObject : public JSNonFinalObject {
+class RegExpObject final : public JSNonFinalObject {
 public:
-    typedef JSNonFinalObject Base;
+    using Base = JSNonFinalObject;
     static const unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames;
 
     static RegExpObject* create(VM& vm, Structure* structure, RegExp* regExp)
@@ -138,12 +138,4 @@ private:
     uint8_t m_lastIndexIsWritable;
 };
 
-RegExpObject* asRegExpObject(JSValue);
-
-inline RegExpObject* asRegExpObject(JSValue value)
-{
-    ASSERT(asObject(value)->inherits(*value.getObject()->vm(), RegExpObject::info()));
-    return static_cast<RegExpObject*>(asObject(value));
-}
-
 } // namespace JSC
index 37402a0..37a9dec 100644 (file)
@@ -103,14 +103,15 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncTestFast(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, RegExpObject::info()))
+    auto* regexp = jsDynamicCast<RegExpObject*>(vm, thisValue);
+    if (UNLIKELY(!regexp))
         return throwVMTypeError(exec, scope);
     JSString* string = exec->argument(0).toStringOrNull(exec);
     EXCEPTION_ASSERT(!!scope.exception() == !string);
     if (!string)
         return JSValue::encode(jsUndefined());
     scope.release();
-    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->test(exec, exec->lexicalGlobalObject(), string)));
+    return JSValue::encode(jsBoolean(regexp->test(exec, exec->lexicalGlobalObject(), string)));
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec)
@@ -119,19 +120,20 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, RegExpObject::info()))
+    auto* regexp = jsDynamicCast<RegExpObject*>(vm, thisValue);
+    if (UNLIKELY(!regexp))
         return throwVMTypeError(exec, scope, "Builtin RegExp exec can only be called on a RegExp object");
     JSString* string = exec->argument(0).toStringOrNull(exec);
     EXCEPTION_ASSERT(!!scope.exception() == !string);
     if (!string)
         return JSValue::encode(jsUndefined());
     scope.release();
-    return JSValue::encode(asRegExpObject(thisValue)->exec(exec, exec->lexicalGlobalObject(), string));
+    return JSValue::encode(regexp->exec(exec, exec->lexicalGlobalObject(), string));
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoFuncMatchFast(ExecState* exec)
 {
-    RegExpObject* thisObject = asRegExpObject(exec->thisValue());
+    RegExpObject* thisObject = jsCast<RegExpObject*>(exec->thisValue());
     JSString* string = jsCast<JSString*>(exec->uncheckedArgument(0));
     if (!thisObject->regExp()->global())
         return JSValue::encode(thisObject->exec(exec, exec->lexicalGlobalObject(), string));
@@ -144,17 +146,18 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, RegExpObject::info()))
+    auto* thisRegExp = jsDynamicCast<RegExpObject*>(vm, thisValue);
+    if (UNLIKELY(!thisRegExp))
         return throwVMTypeError(exec, scope);
 
     RegExp* regExp;
     JSValue arg0 = exec->argument(0);
     JSValue arg1 = exec->argument(1);
     
-    if (arg0.inherits(vm, RegExpObject::info())) {
+    if (auto* regExpObject = jsDynamicCast<RegExpObject*>(vm, arg0)) {
         if (!arg1.isUndefined())
             return throwVMTypeError(exec, scope, ASCIILiteral("Cannot supply flags when constructing one RegExp from another."));
-        regExp = asRegExpObject(arg0)->regExp();
+        regExp = regExpObject->regExp();
     } else {
         String pattern = arg0.isUndefined() ? emptyString() : arg0.toWTFString(exec);
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
@@ -172,10 +175,10 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec)
     if (!regExp->isValid())
         return throwVMError(exec, scope, createSyntaxError(exec, regExp->errorMessage()));
 
-    asRegExpObject(thisValue)->setRegExp(vm, regExp);
+    thisRegExp->setRegExp(vm, regExp);
     scope.release();
-    asRegExpObject(thisValue)->setLastIndex(exec, 0);
-    return JSValue::encode(thisValue);
+    thisRegExp->setLastIndex(exec, 0);
+    return JSValue::encode(thisRegExp);
 }
 
 typedef std::array<char, 6 + 1> FlagsString; // 6 different flags and a null character terminator.
@@ -255,13 +258,14 @@ EncodedJSValue JSC_HOST_CALL regExpProtoGetterGlobal(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue thisValue = exec->thisValue();
-    if (UNLIKELY(!thisValue.inherits(vm, RegExpObject::info()))) {
-        if (thisValue.inherits(vm, RegExpPrototype::info()))
+    auto* regexp = jsDynamicCast<RegExpObject*>(vm, thisValue);
+    if (UNLIKELY(!regexp)) {
+        if (thisValue.inherits<RegExpPrototype>(vm))
             return JSValue::encode(jsUndefined());
         return throwVMTypeError(exec, scope, ASCIILiteral("The RegExp.prototype.global getter can only be called on a RegExp object"));
     }
 
-    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->regExp()->global()));
+    return JSValue::encode(jsBoolean(regexp->regExp()->global()));
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoGetterIgnoreCase(ExecState* exec)
@@ -270,13 +274,14 @@ EncodedJSValue JSC_HOST_CALL regExpProtoGetterIgnoreCase(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue thisValue = exec->thisValue();
-    if (UNLIKELY(!thisValue.inherits(vm, RegExpObject::info()))) {
-        if (thisValue.inherits(vm, RegExpPrototype::info()))
+    auto* regexp = jsDynamicCast<RegExpObject*>(vm, thisValue);
+    if (UNLIKELY(!regexp)) {
+        if (thisValue.inherits<RegExpPrototype>(vm))
             return JSValue::encode(jsUndefined());
         return throwVMTypeError(exec, scope, ASCIILiteral("The RegExp.prototype.ignoreCase getter can only be called on a RegExp object"));
     }
 
-    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->regExp()->ignoreCase()));
+    return JSValue::encode(jsBoolean(regexp->regExp()->ignoreCase()));
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoGetterMultiline(ExecState* exec)
@@ -285,13 +290,14 @@ EncodedJSValue JSC_HOST_CALL regExpProtoGetterMultiline(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue thisValue = exec->thisValue();
-    if (UNLIKELY(!thisValue.inherits(vm, RegExpObject::info()))) {
-        if (thisValue.inherits(vm, RegExpPrototype::info()))
+    auto* regexp = jsDynamicCast<RegExpObject*>(vm, thisValue);
+    if (UNLIKELY(!regexp)) {
+        if (thisValue.inherits<RegExpPrototype>(vm))
             return JSValue::encode(jsUndefined());
         return throwVMTypeError(exec, scope, ASCIILiteral("The RegExp.prototype.multiline getter can only be called on a RegExp object"));
     }
 
-    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->regExp()->multiline()));
+    return JSValue::encode(jsBoolean(regexp->regExp()->multiline()));
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoGetterDotAll(ExecState* exec)
@@ -300,13 +306,14 @@ EncodedJSValue JSC_HOST_CALL regExpProtoGetterDotAll(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
     
     JSValue thisValue = exec->thisValue();
-    if (UNLIKELY(!thisValue.inherits(vm, RegExpObject::info()))) {
-        if (thisValue.inherits(vm, RegExpPrototype::info()))
+    auto* regexp = jsDynamicCast<RegExpObject*>(vm, thisValue);
+    if (UNLIKELY(!regexp)) {
+        if (thisValue.inherits<RegExpPrototype>(vm))
             return JSValue::encode(jsUndefined());
         return throwVMTypeError(exec, scope, ASCIILiteral("The RegExp.prototype.dotAll getter can only be called on a RegExp object"));
     }
     
-    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->regExp()->dotAll()));
+    return JSValue::encode(jsBoolean(regexp->regExp()->dotAll()));
 }
     
 EncodedJSValue JSC_HOST_CALL regExpProtoGetterSticky(ExecState* exec)
@@ -315,13 +322,14 @@ EncodedJSValue JSC_HOST_CALL regExpProtoGetterSticky(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue thisValue = exec->thisValue();
-    if (UNLIKELY(!thisValue.inherits(vm, RegExpObject::info()))) {
-        if (thisValue.inherits(vm, RegExpPrototype::info()))
+    auto* regexp = jsDynamicCast<RegExpObject*>(vm, thisValue);
+    if (UNLIKELY(!regexp)) {
+        if (thisValue.inherits<RegExpPrototype>(vm))
             return JSValue::encode(jsUndefined());
         return throwVMTypeError(exec, scope, ASCIILiteral("The RegExp.prototype.sticky getter can only be called on a RegExp object"));
     }
     
-    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->regExp()->sticky()));
+    return JSValue::encode(jsBoolean(regexp->regExp()->sticky()));
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoGetterUnicode(ExecState* exec)
@@ -330,13 +338,14 @@ EncodedJSValue JSC_HOST_CALL regExpProtoGetterUnicode(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue thisValue = exec->thisValue();
-    if (UNLIKELY(!thisValue.inherits(vm, RegExpObject::info()))) {
-        if (thisValue.inherits(vm, RegExpPrototype::info()))
+    auto* regexp = jsDynamicCast<RegExpObject*>(vm, thisValue);
+    if (UNLIKELY(!regexp)) {
+        if (thisValue.inherits<RegExpPrototype>(vm))
             return JSValue::encode(jsUndefined());
         return throwVMTypeError(exec, scope, ASCIILiteral("The RegExp.prototype.unicode getter can only be called on a RegExp object"));
     }
     
-    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->regExp()->unicode()));
+    return JSValue::encode(jsBoolean(regexp->regExp()->unicode()));
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoGetterFlags(ExecState* exec)
@@ -466,13 +475,14 @@ EncodedJSValue JSC_HOST_CALL regExpProtoGetterSource(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue thisValue = exec->thisValue();
-    if (UNLIKELY(!thisValue.inherits(vm, RegExpObject::info()))) {
-        if (thisValue.inherits(vm, RegExpPrototype::info()))
+    auto* regexp = jsDynamicCast<RegExpObject*>(vm, thisValue);
+    if (UNLIKELY(!regexp)) {
+        if (thisValue.inherits<RegExpPrototype>(vm))
             return JSValue::encode(jsString(exec, ASCIILiteral("(?:)")));
         return throwVMTypeError(exec, scope, ASCIILiteral("The RegExp.prototype.source getter can only be called on a RegExp object"));
     }
 
-    String pattern = asRegExpObject(thisValue)->regExp()->pattern();
+    String pattern = regexp->regExp()->pattern();
     if (pattern.is8Bit())
         return JSValue::encode(regExpProtoGetterSourceInternal(exec, pattern, pattern.characters8(), pattern.length()));
     return JSValue::encode(regExpProtoGetterSourceInternal(exec, pattern, pattern.characters16(), pattern.length()));
@@ -483,7 +493,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncSearchFast(ExecState* exec)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     JSValue thisValue = exec->thisValue();
-    RegExp* regExp = asRegExpObject(thisValue)->regExp();
+    RegExp* regExp = jsCast<RegExpObject*>(thisValue)->regExp();
 
     JSString* string = exec->uncheckedArgument(0).toString(exec);
     String s = string->value(exec);
@@ -590,7 +600,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncSplitFast(ExecState* exec)
     // 1. [handled by JS builtin] Let rx be the this value.
     // 2. [handled by JS builtin] If Type(rx) is not Object, throw a TypeError exception.
     JSValue thisValue = exec->thisValue();
-    RegExp* regexp = asRegExpObject(thisValue)->regExp();
+    RegExp* regexp = jsCast<RegExpObject*>(thisValue)->regExp();
 
     // 3. [handled by JS builtin] Let S be ? ToString(string).
     JSString* inputString = exec->argument(0).toString(exec);
index 24fff00..506c4c5 100644 (file)
@@ -71,14 +71,6 @@ protected:
     JS_EXPORT_PRIVATE StringObject(VM&, Structure*);
 };
 
-StringObject* asStringObject(JSValue);
-
-inline StringObject* asStringObject(JSValue value)
-{
-    ASSERT(asObject(value)->inherits(*value.getObject()->vm(), StringObject::info()));
-    return static_cast<StringObject*>(asObject(value));
-}
-
 JS_EXPORT_PRIVATE StringObject* constructString(VM&, JSGlobalObject*, JSValue);
 
 // Helper for producing a JSString for 'string', where 'string' was been produced by
index 6e41ec7..a0d3601 100644 (file)
@@ -533,7 +533,7 @@ static ALWAYS_INLINE JSString* replaceUsingRegExpSearch(
     const String& source = string->value(exec);
     unsigned sourceLen = source.length();
     RETURN_IF_EXCEPTION(scope, nullptr);
-    RegExpObject* regExpObject = asRegExpObject(searchValue);
+    RegExpObject* regExpObject = jsCast<RegExpObject*>(searchValue);
     RegExp* regExp = regExpObject->regExp();
     bool global = regExp->global();
     bool hasNamedCaptures = regExp->hasNamedCaptures();
@@ -954,7 +954,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncRepeatCharacter(ExecState* exec)
 ALWAYS_INLINE JSString* replace(
     VM& vm, ExecState* exec, JSString* string, JSValue searchValue, JSValue replaceValue)
 {
-    if (searchValue.inherits(vm, RegExpObject::info()))
+    if (searchValue.inherits<RegExpObject>(vm))
         return replaceUsingRegExpSearch(vm, exec, string, searchValue, replaceValue);
     return replaceUsingStringSearch(vm, exec, string, searchValue, replaceValue);
 }
@@ -983,7 +983,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplaceUsingRegExp(ExecState* exec)
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     JSValue searchValue = exec->argument(0);
-    if (!searchValue.inherits(vm, RegExpObject::info()))
+    if (!searchValue.inherits<RegExpObject>(vm))
         return JSValue::encode(jsUndefined());
 
     scope.release();
@@ -1025,8 +1025,9 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec)
     if (thisValue.isString())
         return JSValue::encode(thisValue);
 
-    if (thisValue.inherits(vm, StringObject::info()))
-        return JSValue::encode(asStringObject(thisValue)->internalValue());
+    auto* stringObject = jsDynamicCast<StringObject*>(vm, thisValue);
+    if (stringObject)
+        return JSValue::encode(stringObject->internalValue());
 
     return throwVMTypeError(exec, scope);
 }
index d166614..3d798c6 100644 (file)
@@ -85,7 +85,7 @@ EncodedJSValue JSC_HOST_CALL symbolProtoFuncToString(ExecState* exec)
         if (!thisValue.isObject())
             return throwVMTypeError(exec, scope, SymbolToStringTypeError);
         JSObject* thisObject = asObject(thisValue);
-        if (!thisObject->inherits(vm, SymbolObject::info()))
+        if (!thisObject->inherits<SymbolObject>(vm))
             return throwVMTypeError(exec, scope, SymbolToStringTypeError);
         symbol = asSymbol(jsCast<SymbolObject*>(thisObject)->internalValue());
     }
@@ -106,7 +106,7 @@ EncodedJSValue JSC_HOST_CALL symbolProtoFuncValueOf(ExecState* exec)
         return throwVMTypeError(exec, scope, SymbolValueOfTypeError);
 
     JSObject* thisObject = asObject(thisValue);
-    if (!thisObject->inherits(vm, SymbolObject::info()))
+    if (!thisObject->inherits<SymbolObject>(vm))
         return throwVMTypeError(exec, scope, SymbolValueOfTypeError);
 
     return JSValue::encode(jsCast<SymbolObject*>(thisObject)->internalValue());
index 9e08afe..42a9b5f 100644 (file)
@@ -949,7 +949,7 @@ static EncodedJSValue customGetAccessor(ExecState*, EncodedJSValue thisValue, Pr
 
 static EncodedJSValue customGetValue(ExecState* exec, EncodedJSValue slotValue, PropertyName)
 {
-    RELEASE_ASSERT(JSValue::decode(slotValue).inherits(exec->vm(), JSTestCustomGetterSetter::info()));
+    RELEASE_ASSERT(JSValue::decode(slotValue).inherits<JSTestCustomGetterSetter>(exec->vm()));
     // Passed property holder.
     return slotValue;
 }
@@ -971,7 +971,7 @@ static bool customSetValue(ExecState* exec, EncodedJSValue slotValue, EncodedJSV
 {
     VM& vm = exec->vm();
 
-    RELEASE_ASSERT(JSValue::decode(slotValue).inherits(exec->vm(), JSTestCustomGetterSetter::info()));
+    RELEASE_ASSERT(JSValue::decode(slotValue).inherits<JSTestCustomGetterSetter>(exec->vm()));
 
     JSValue value = JSValue::decode(encodedValue);
     RELEASE_ASSERT(value.isObject());
index 14487f0..afc5e16 100644 (file)
@@ -94,12 +94,12 @@ ALWAYS_INLINE Vector<uint8_t> createSourceBufferFromValue(VM& vm, ExecState* exe
 
 ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JSObject* object, WebAssemblyFunction*& wasmFunction, WebAssemblyWrapperFunction*& wasmWrapperFunction)
 {
-    if (object->inherits(vm, WebAssemblyFunction::info())) {
+    if (object->inherits<WebAssemblyFunction>(vm)) {
         wasmFunction = jsCast<WebAssemblyFunction*>(object);
         wasmWrapperFunction = nullptr;
         return true;
     }
-    if (object->inherits(vm, WebAssemblyWrapperFunction::info())) {
+    if (object->inherits<WebAssemblyWrapperFunction>(vm)) {
         wasmWrapperFunction = jsCast<WebAssemblyWrapperFunction*>(object);
         wasmFunction = nullptr;
         return true;
index 52c5da2..7a1aa38 100644 (file)
@@ -60,7 +60,7 @@ WebAssemblyWrapperFunction::WebAssemblyWrapperFunction(VM& vm, JSGlobalObject* g
 
 WebAssemblyWrapperFunction* WebAssemblyWrapperFunction::create(VM& vm, JSGlobalObject* globalObject, JSObject* function, unsigned importIndex, JSWebAssemblyInstance* instance, Wasm::SignatureIndex signatureIndex)
 {
-    ASSERT_WITH_MESSAGE(!function->inherits(vm, WebAssemblyWrapperFunction::info()), "We should never double wrap a wrapper function.");
+    ASSERT_WITH_MESSAGE(!function->inherits<WebAssemblyWrapperFunction>(vm), "We should never double wrap a wrapper function.");
     String name = "";
     NativeExecutable* executable = vm.getHostFunction(callWebAssemblyWrapperFunction, NoIntrinsic, callHostFunctionAsConstructor, nullptr, name);
     WebAssemblyWrapperFunction* result = new (NotNull, allocateCell<WebAssemblyWrapperFunction>(vm.heap)) WebAssemblyWrapperFunction(vm, globalObject, globalObject->webAssemblyWrapperFunctionStructure(), Wasm::CallableFunction { signatureIndex, &instance->instance().importFunctionInfo(importIndex)->wasmToEmbedderStubExecutableAddress } );
index e61f189..acc7d0a 100644 (file)
@@ -1,3 +1,67 @@
+2018-03-08  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [JSC] Add inherits<T>(VM&) leveraging JSCast fast path
+        https://bugs.webkit.org/show_bug.cgi?id=183429
+
+        Reviewed by Mark Lam.
+
+        * bindings/js/IDBBindingUtilities.cpp:
+        (WebCore::createIDBKeyFromValue):
+        * bindings/js/JSDOMConvertDate.cpp:
+        (WebCore::valueToDate):
+        * bindings/js/JSDOMGlobalObject.cpp:
+        (WebCore::JSDOMGlobalObject::scriptExecutionContext const):
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::JSDOMWindow::toWrapped):
+        * bindings/js/JSEventTargetCustom.cpp:
+        * bindings/js/JSNodeCustom.cpp:
+        (WebCore::JSNode::pushEventHandlerScope const):
+        * bindings/js/JSXPathNSResolverCustom.cpp:
+        (WebCore::JSXPathNSResolver::toWrapped):
+        * bindings/js/ScriptState.cpp:
+        (WebCore::domWindowFromExecState):
+        (WebCore::scriptExecutionContextFromExecState):
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneSerializer::isArray):
+        (WebCore::CloneSerializer::isMap):
+        (WebCore::CloneSerializer::isSet):
+        (WebCore::CloneSerializer::dumpArrayBufferView):
+        (WebCore::CloneSerializer::dumpDOMPoint):
+        (WebCore::CloneSerializer::dumpDOMRect):
+        (WebCore::CloneSerializer::dumpDOMMatrix):
+        (WebCore::CloneSerializer::dumpIfTerminal):
+        (WebCore::CloneDeserializer::CloneDeserializer):
+        (WebCore::CloneDeserializer::readArrayBufferView):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateOverloadDispatcher):
+        * bindings/scripts/test/JS/JSTestObj.cpp:
+        (WebCore::jsTestObjPrototypeFunctionOverloadedMethodOverloadDispatcher):
+        (WebCore::jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameterOverloadDispatcher):
+        (WebCore::jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnionOverloadDispatcher):
+        (WebCore::jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnionsOverloadDispatcher):
+        (WebCore::jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnionOverloadDispatcher):
+        (WebCore::jsTestObjPrototypeFunctionOverloadWithNullableUnionOverloadDispatcher):
+        (WebCore::jsTestObjPrototypeFunctionOverloadWithNullableNonDistinguishingParameterOverloadDispatcher):
+        (WebCore::jsTestObjPrototypeFunctionTestPromiseOverloadedFunctionOverloadDispatcher):
+        * bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp:
+        (WebCore::JSTestOverloadedConstructorsConstructor::construct):
+        * bridge/c/c_instance.cpp:
+        (JSC::Bindings::CInstance::invokeMethod):
+        * bridge/objc/WebScriptObject.mm:
+        (+[WebScriptObject _convertValueToObjcValue:originRootObject:rootObject:]):
+        * bridge/objc/objc_instance.mm:
+        (ObjcInstance::invokeMethod):
+        * bridge/objc/objc_runtime.mm:
+        (JSC::Bindings::callObjCFallbackObject):
+        * bridge/runtime_method.cpp:
+        (JSC::callRuntimeMethod):
+        * bridge/runtime_object.cpp:
+        (JSC::Bindings::callRuntimeObject):
+        (JSC::Bindings::callRuntimeConstructor):
+        * inspector/WebInjectedScriptHost.cpp:
+        (WebCore::WebInjectedScriptHost::subtype):
+        (WebCore::WebInjectedScriptHost::isHTMLAllCollection):
+
 2018-03-08  Tim Horton  <timothy_horton@apple.com>
 
         Stop linking ApplicationServices directly
index d78e220..7dda1fa 100644 (file)
@@ -151,7 +151,7 @@ static RefPtr<IDBKey> createIDBKeyFromValue(ExecState& exec, JSValue value, Vect
     if (value.isString())
         return IDBKey::createString(asString(value)->value(&exec));
 
-    if (value.inherits(vm, DateInstance::info())) {
+    if (value.inherits<DateInstance>(vm)) {
         auto dateValue = valueToDate(exec, value);
         if (!std::isnan(dateValue))
             return IDBKey::createDate(dateValue);
@@ -159,8 +159,7 @@ static RefPtr<IDBKey> createIDBKeyFromValue(ExecState& exec, JSValue value, Vect
 
     if (value.isObject()) {
         JSObject* object = asObject(value);
-        if (isJSArray(object) || object->inherits(vm, JSArray::info())) {
-            JSArray* array = asArray(object);
+        if (auto* array = jsDynamicCast<JSArray*>(vm, object)) {
             size_t length = array->length();
 
             if (stack.contains(array))
index 80b53e8..c312509 100644 (file)
@@ -40,7 +40,7 @@ double valueToDate(ExecState& state, JSValue value)
 {
     if (value.isNumber())
         return value.asNumber();
-    if (!value.inherits(state.vm(), DateInstance::info()))
+    if (!value.inherits<DateInstance>(state.vm()))
         return std::numeric_limits<double>::quiet_NaN();
     return static_cast<DateInstance*>(value.toObject(&state))->internalNumber();
 }
index bcf6870..7a35484 100644 (file)
@@ -195,9 +195,9 @@ void JSDOMGlobalObject::finishCreation(VM& vm, JSObject* thisValue)
 
 ScriptExecutionContext* JSDOMGlobalObject::scriptExecutionContext() const
 {
-    if (inherits(vm(), JSDOMWindowBase::info()))
+    if (inherits<JSDOMWindowBase>(vm()))
         return jsCast<const JSDOMWindowBase*>(this)->scriptExecutionContext();
-    if (inherits(vm(), JSWorkerGlobalScopeBase::info()))
+    if (inherits<JSWorkerGlobalScopeBase>(vm()))
         return jsCast<const JSWorkerGlobalScopeBase*>(this)->scriptExecutionContext();
     dataLog("Unexpected global object: ", JSValue(this), "\n");
     RELEASE_ASSERT_NOT_REACHED();
index cf7d909..e589ad6 100644 (file)
@@ -459,9 +459,9 @@ DOMWindow* JSDOMWindow::toWrapped(VM& vm, JSValue value)
     if (!value.isObject())
         return nullptr;
     JSObject* object = asObject(value);
-    if (object->inherits(vm, JSDOMWindow::info()))
+    if (object->inherits<JSDOMWindow>(vm))
         return &jsCast<JSDOMWindow*>(object)->wrapped();
-    if (object->inherits(vm, JSDOMWindowProxy::info()))
+    if (object->inherits<JSDOMWindowProxy>(vm))
         return &jsCast<JSDOMWindowProxy*>(object)->wrapped();
     return nullptr;
 }
index f4a0294..b4f0cce 100644 (file)
@@ -57,7 +57,7 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget& targ
 #undef TRY_TO_WRAP_WITH_INTERFACE
 
 #define TRY_TO_UNWRAP_WITH_INTERFACE(interfaceName) \
-    if (value.inherits(vm, JS##interfaceName::info()))                      \
+    if (value.inherits<JS##interfaceName>(vm)) \
         return &jsCast<JS##interfaceName*>(asObject(value))->wrapped();
 
 EventTarget* JSEventTarget::toWrapped(VM& vm, JSValue value)
index 9f36e74..09a70f2 100644 (file)
@@ -111,7 +111,7 @@ bool JSNodeOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, v
 
 JSScope* JSNode::pushEventHandlerScope(ExecState* exec, JSScope* node) const
 {
-    if (inherits(exec->vm(), JSHTMLElement::info()))
+    if (inherits<JSHTMLElement>(exec->vm()))
         return jsCast<const JSHTMLElement*>(this)->pushEventHandlerScope(exec, node);
     return node;
 }
index 0da5128..19e92b6 100644 (file)
@@ -35,7 +35,7 @@ using namespace JSC;
 
 RefPtr<XPathNSResolver> JSXPathNSResolver::toWrapped(VM& vm, ExecState& state, JSValue value)
 {
-    if (value.inherits(vm, JSXPathNSResolver::info()))
+    if (value.inherits<JSXPathNSResolver>(vm))
         return &jsCast<JSXPathNSResolver*>(asObject(value))->wrapped();
 
     auto result = JSCustomXPathNSResolver::create(state, value);
index e4e62a1..8c29c78 100644 (file)
@@ -50,7 +50,7 @@ DOMWindow* domWindowFromExecState(JSC::ExecState* scriptState)
 {
     JSC::JSGlobalObject* globalObject = scriptState->lexicalGlobalObject();
     JSC::VM& vm = globalObject->vm();
-    if (!globalObject->inherits(vm, JSDOMWindowBase::info()))
+    if (!globalObject->inherits<JSDOMWindowBase>(vm))
         return nullptr;
     return &JSC::jsCast<JSDOMWindowBase*>(globalObject)->wrapped();
 }
@@ -66,7 +66,7 @@ ScriptExecutionContext* scriptExecutionContextFromExecState(JSC::ExecState* scri
 {
     JSC::JSGlobalObject* globalObject = scriptState->lexicalGlobalObject();
     JSC::VM& vm = globalObject->vm();
-    if (!globalObject->inherits(vm, JSDOMGlobalObject::info()))
+    if (!globalObject->inherits<JSDOMGlobalObject>(vm))
         return nullptr;
     return JSC::jsCast<JSDOMGlobalObject*>(globalObject)->scriptExecutionContext();
 }
index b8569a3..532c717 100644 (file)
@@ -604,7 +604,7 @@ private:
         if (!value.isObject())
             return false;
         JSObject* object = asObject(value);
-        return isJSArray(object) || object->inherits(vm, JSArray::info());
+        return object->inherits<JSArray>(vm);
     }
 
     bool isMap(VM& vm, JSValue value)
@@ -612,14 +612,14 @@ private:
         if (!value.isObject())
             return false;
         JSObject* object = asObject(value);
-        return object->inherits(vm, JSMap::info());
+        return object->inherits<JSMap>(vm);
     }
     bool isSet(VM& vm, JSValue value)
     {
         if (!value.isObject())
             return false;
         JSObject* object = asObject(value);
-        return object->inherits(vm, JSSet::info());
+        return object->inherits<JSSet>(vm);
     }
 
     bool checkForDuplicate(JSObject* object)
@@ -754,25 +754,25 @@ private:
     {
         VM& vm = m_exec->vm();
         write(ArrayBufferViewTag);
-        if (obj->inherits(vm, JSDataView::info()))
+        if (obj->inherits<JSDataView>(vm))
             write(DataViewTag);
-        else if (obj->inherits(vm, JSUint8ClampedArray::info()))
+        else if (obj->inherits<JSUint8ClampedArray>(vm))
             write(Uint8ClampedArrayTag);
-        else if (obj->inherits(vm, JSInt8Array::info()))
+        else if (obj->inherits<JSInt8Array>(vm))
             write(Int8ArrayTag);
-        else if (obj->inherits(vm, JSUint8Array::info()))
+        else if (obj->inherits<JSUint8Array>(vm))
             write(Uint8ArrayTag);
-        else if (obj->inherits(vm, JSInt16Array::info()))
+        else if (obj->inherits<JSInt16Array>(vm))
             write(Int16ArrayTag);
-        else if (obj->inherits(vm, JSUint16Array::info()))
+        else if (obj->inherits<JSUint16Array>(vm))
             write(Uint16ArrayTag);
-        else if (obj->inherits(vm, JSInt32Array::info()))
+        else if (obj->inherits<JSInt32Array>(vm))
             write(Int32ArrayTag);
-        else if (obj->inherits(vm, JSUint32Array::info()))
+        else if (obj->inherits<JSUint32Array>(vm))
             write(Uint32ArrayTag);
-        else if (obj->inherits(vm, JSFloat32Array::info()))
+        else if (obj->inherits<JSFloat32Array>(vm))
             write(Float32ArrayTag);
-        else if (obj->inherits(vm, JSFloat64Array::info()))
+        else if (obj->inherits<JSFloat64Array>(vm))
             write(Float64ArrayTag);
         else
             return false;
@@ -800,7 +800,7 @@ private:
     void dumpDOMPoint(JSObject* obj)
     {
         VM& vm = m_exec->vm();
-        if (obj->inherits(vm, JSDOMPoint::info()))
+        if (obj->inherits<JSDOMPoint>(vm))
             write(DOMPointTag);
         else
             write(DOMPointReadOnlyTag);
@@ -811,7 +811,7 @@ private:
     void dumpDOMRect(JSObject* obj)
     {
         VM& vm = m_exec->vm();
-        if (obj->inherits(vm, JSDOMRect::info()))
+        if (obj->inherits<JSDOMRect>(vm))
             write(DOMRectTag);
         else
             write(DOMRectReadOnlyTag);
@@ -826,7 +826,7 @@ private:
     void dumpDOMMatrix(JSObject* obj)
     {
         VM& vm = m_exec->vm();
-        if (obj->inherits(vm, JSDOMMatrix::info()))
+        if (obj->inherits<JSDOMMatrix>(vm))
             write(DOMMatrixTag);
         else
             write(DOMMatrixReadOnlyTag);
@@ -891,36 +891,34 @@ private:
         }
 
         VM& vm = m_exec->vm();
-        if (value.isObject() && asObject(value)->inherits(vm, DateInstance::info())) {
-            write(DateTag);
-            write(asDateInstance(value)->internalNumber());
-            return true;
-        }
-
         if (isArray(vm, value))
             return false;
 
         if (value.isObject()) {
             auto* obj = asObject(value);
-            if (obj->inherits(vm, BooleanObject::info())) {
-                if (!startObjectInternal(obj)) // handle duplicates
+            if (auto* dateObject = jsDynamicCast<DateInstance*>(vm, obj)) {
+                write(DateTag);
+                write(dateObject->internalNumber());
+                return true;
+            }
+            if (auto* booleanObject = jsDynamicCast<BooleanObject*>(vm, obj)) {
+                if (!startObjectInternal(booleanObject)) // handle duplicates
                     return true;
-                write(asBooleanObject(value)->internalValue().toBoolean(m_exec) ? TrueObjectTag : FalseObjectTag);
+                write(booleanObject->internalValue().toBoolean(m_exec) ? TrueObjectTag : FalseObjectTag);
                 return true;
             }
-            if (obj->inherits(vm, StringObject::info())) {
-                if (!startObjectInternal(obj)) // handle duplicates
+            if (auto* stringObject = jsDynamicCast<StringObject*>(vm, obj)) {
+                if (!startObjectInternal(stringObject)) // handle duplicates
                     return true;
-                String str = asString(asStringObject(value)->internalValue())->value(m_exec);
+                String str = asString(stringObject->internalValue())->value(m_exec);
                 dumpStringObject(str);
                 return true;
             }
-            if (obj->inherits(vm, NumberObject::info())) {
-                if (!startObjectInternal(obj)) // handle duplicates
+            if (auto* numberObject = jsDynamicCast<NumberObject*>(vm, obj)) {
+                if (!startObjectInternal(numberObject)) // handle duplicates
                     return true;
                 write(NumberObjectTag);
-                NumberObject* obj = static_cast<NumberObject*>(asObject(value));
-                write(obj->internalValue().asNumber());
+                write(numberObject->internalValue().asNumber());
                 return true;
             }
             if (auto* file = JSFile::toWrapped(vm, obj)) {
@@ -951,8 +949,7 @@ private:
                 write(data->data()->data(), data->data()->length());
                 return true;
             }
-            if (obj->inherits(vm, RegExpObject::info())) {
-                auto* regExp = asRegExpObject(obj);
+            if (auto* regExp = jsDynamicCast<RegExpObject*>(vm, obj)) {
                 char flags[3];
                 int flagCount = 0;
                 if (regExp->regExp()->global())
@@ -966,7 +963,7 @@ private:
                 write(String(flags, flagCount));
                 return true;
             }
-            if (obj->inherits(vm, JSMessagePort::info())) {
+            if (obj->inherits<JSMessagePort>(vm)) {
                 auto index = m_transferredMessagePorts.find(obj);
                 if (index != m_transferredMessagePorts.end()) {
                     write(MessagePortReferenceTag);
@@ -1007,7 +1004,7 @@ private:
                 write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength());
                 return true;
             }
-            if (obj->inherits(vm, JSArrayBufferView::info())) {
+            if (obj->inherits<JSArrayBufferView>(vm)) {
                 if (checkForDuplicate(obj))
                     return true;
                 bool success = dumpArrayBufferView(obj, code);
@@ -1051,19 +1048,19 @@ private:
                 return true;
             }
 #endif
-            if (obj->inherits(vm, JSDOMPointReadOnly::info())) {
+            if (obj->inherits<JSDOMPointReadOnly>(vm)) {
                 dumpDOMPoint(obj);
                 return true;
             }
-            if (obj->inherits(vm, JSDOMRectReadOnly::info())) {
+            if (obj->inherits<JSDOMRectReadOnly>(vm)) {
                 dumpDOMRect(obj);
                 return true;
             }
-            if (obj->inherits(vm, JSDOMMatrixReadOnly::info())) {
+            if (obj->inherits<JSDOMMatrixReadOnly>(vm)) {
                 dumpDOMMatrix(obj);
                 return true;
             }
-            if (obj->inherits(vm, JSDOMQuad::info())) {
+            if (obj->inherits<JSDOMQuad>(vm)) {
                 dumpDOMQuad(obj);
                 return true;
             }
@@ -1755,7 +1752,7 @@ private:
         const Vector<uint8_t>& buffer)
         : CloneBase(exec)
         , m_globalObject(globalObject)
-        , m_isDOMGlobalObject(globalObject->inherits(globalObject->vm(), JSDOMGlobalObject::info()))
+        , m_isDOMGlobalObject(globalObject->inherits<JSDOMGlobalObject>(globalObject->vm()))
         , m_ptr(buffer.data())
         , m_end(buffer.data() + buffer.size())
         , m_version(0xFFFFFFFF)
@@ -1777,7 +1774,7 @@ private:
         )
         : CloneBase(exec)
         , m_globalObject(globalObject)
-        , m_isDOMGlobalObject(globalObject->inherits(globalObject->vm(), JSDOMGlobalObject::info()))
+        , m_isDOMGlobalObject(globalObject->inherits<JSDOMGlobalObject>(globalObject->vm()))
         , m_ptr(buffer.data())
         , m_end(buffer.data() + buffer.size())
         , m_version(0xFFFFFFFF)
@@ -2048,7 +2045,7 @@ private:
         if (!read(byteLength))
             return false;
         JSObject* arrayBufferObj = asObject(readTerminal());
-        if (!arrayBufferObj || !arrayBufferObj->inherits(vm, JSArrayBuffer::info()))
+        if (!arrayBufferObj || !arrayBufferObj->inherits<JSArrayBuffer>(vm))
             return false;
 
         unsigned elementSize = typedArrayElementSize(arrayBufferViewSubtag);
index d9eaf8c..c597d5a 100644 (file)
@@ -3400,16 +3400,16 @@ sub GenerateOverloadDispatcher
                     if ($codeGenerator->IsWrapperType($subtype) || $codeGenerator->IsBufferSourceType($subtype)) {
                         if ($subtype->name eq "DOMWindow") {
                             AddToImplIncludes("JSDOMWindowProxy.h");
-                            &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && (asObject(distinguishingArg)->inherits(vm, JSDOMWindowProxy::info()) || asObject(distinguishingArg)->inherits(vm, JSDOMWindow::info()))");
+                            &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && (asObject(distinguishingArg)->inherits<JSDOMWindowProxy>(vm) || asObject(distinguishingArg)->inherits<JSDOMWindow>(vm))");
                         } else {
-                            &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JS" . $subtype->name . "::info())");
+                            &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JS" . $subtype->name . ">(vm)");
                         }
                     }
                 }
             }
 
             $overload = GetOverloadThatMatches($S, $d, \&$isObjectOrErrorOrDOMExceptionParameter);
-            &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSDOMException::info())");
+            &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSDOMException>(vm)");
 
             $overload = GetOverloadThatMatches($S, $d, \&$isObjectOrErrorParameter);
             &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->type() == ErrorInstanceType");
index db4f4b1..9cebb77 100644 (file)
@@ -7021,17 +7021,17 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodOver
         JSValue distinguishingArg = state->uncheckedArgument(0);
         if (distinguishingArg.isUndefinedOrNull())
             return jsTestObjPrototypeFunctionOverloadedMethod2Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestObj::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestObj>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethod2Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestCallbackInterface::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestCallbackInterface>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethod5Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSDOMStringList::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSDOMStringList>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethod6Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestObj::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestObj>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethod8Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && (asObject(distinguishingArg)->inherits(vm, JSDOMWindowProxy::info()) || asObject(distinguishingArg)->inherits(vm, JSDOMWindow::info())))
+        if (distinguishingArg.isObject() && (asObject(distinguishingArg)->inherits<JSDOMWindowProxy>(vm) || asObject(distinguishingArg)->inherits<JSDOMWindow>(vm)))
             return jsTestObjPrototypeFunctionOverloadedMethod9Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSBlob::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSBlob>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethod13Body(state, castedThis, throwScope);
         if (hasIteratorMethod(*state, distinguishingArg))
             return jsTestObjPrototypeFunctionOverloadedMethod7Body(state, castedThis, throwScope);
@@ -7045,7 +7045,7 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodOver
         JSValue distinguishingArg = state->uncheckedArgument(1);
         if (distinguishingArg.isUndefined())
             return jsTestObjPrototypeFunctionOverloadedMethod2Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSBlob::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSBlob>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethod13Body(state, castedThis, throwScope);
         if (distinguishingArg.isNumber())
             return jsTestObjPrototypeFunctionOverloadedMethod2Body(state, castedThis, throwScope);
@@ -7096,7 +7096,7 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWith
         JSValue distinguishingArg = state->uncheckedArgument(0);
         if (distinguishingArg.isUndefinedOrNull())
             return jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameter2Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestObj::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestObj>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameter2Body(state, castedThis, throwScope);
         return jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameter1Body(state, castedThis, throwScope);
     }
@@ -7104,7 +7104,7 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWith
         JSValue distinguishingArg = state->uncheckedArgument(0);
         if (distinguishingArg.isUndefinedOrNull())
             return jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameter2Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestObj::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestObj>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameter2Body(state, castedThis, throwScope);
         return jsTestObjPrototypeFunctionOverloadedMethodWithOptionalParameter1Body(state, castedThis, throwScope);
     }
@@ -7147,9 +7147,9 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWith
     size_t argsCount = std::min<size_t>(1, state->argumentCount());
     if (argsCount == 1) {
         JSValue distinguishingArg = state->uncheckedArgument(0);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestObj::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestObj>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion1Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestNode::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestNode>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion1Body(state, castedThis, throwScope);
         if (distinguishingArg.isNumber())
             return jsTestObjPrototypeFunctionOverloadedMethodWithDistinguishingUnion2Body(state, castedThis, throwScope);
@@ -7194,11 +7194,11 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWith
     size_t argsCount = std::min<size_t>(1, state->argumentCount());
     if (argsCount == 1) {
         JSValue distinguishingArg = state->uncheckedArgument(0);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestObj::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestObj>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions1Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestNode::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestNode>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions1Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestInterface::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestInterface>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions2Body(state, castedThis, throwScope);
         if (distinguishingArg.isNumber())
             return jsTestObjPrototypeFunctionOverloadedMethodWith2DistinguishingUnions2Body(state, castedThis, throwScope);
@@ -7247,9 +7247,9 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethodWith
     size_t argsCount = std::min<size_t>(2, state->argumentCount());
     if (argsCount == 2) {
         JSValue distinguishingArg = state->uncheckedArgument(1);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestObj::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestObj>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion1Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestNode::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestNode>(vm))
             return jsTestObjPrototypeFunctionOverloadedMethodWithNonDistinguishingUnion2Body(state, castedThis, throwScope);
     }
     return argsCount < 2 ? throwVMError(state, throwScope, createNotEnoughArgumentsError(state)) : throwVMTypeError(state, throwScope);
@@ -7293,9 +7293,9 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadWithNullable
         JSValue distinguishingArg = state->uncheckedArgument(0);
         if (distinguishingArg.isUndefinedOrNull())
             return jsTestObjPrototypeFunctionOverloadWithNullableUnion1Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestObj::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestObj>(vm))
             return jsTestObjPrototypeFunctionOverloadWithNullableUnion1Body(state, castedThis, throwScope);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestNode::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestNode>(vm))
             return jsTestObjPrototypeFunctionOverloadWithNullableUnion1Body(state, castedThis, throwScope);
         if (distinguishingArg.isNumber())
             return jsTestObjPrototypeFunctionOverloadWithNullableUnion2Body(state, castedThis, throwScope);
@@ -7394,7 +7394,7 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadWithNullable
     size_t argsCount = std::min<size_t>(2, state->argumentCount());
     if (argsCount == 2) {
         JSValue distinguishingArg = state->uncheckedArgument(1);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSTestNode::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSTestNode>(vm))
             return jsTestObjPrototypeFunctionOverloadWithNullableNonDistinguishingParameter1Body(state, castedThis, throwScope);
         if (distinguishingArg.isNumber())
             return jsTestObjPrototypeFunctionOverloadWithNullableNonDistinguishingParameter2Body(state, castedThis, throwScope);
@@ -7984,7 +7984,7 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionTestPromiseOverloade
     size_t argsCount = std::min<size_t>(1, state->argumentCount());
     if (argsCount == 1) {
         JSValue distinguishingArg = state->uncheckedArgument(0);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSFetchRequest::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSFetchRequest>(vm))
             return jsTestObjPrototypeFunctionTestPromiseOverloadedFunction2Body(state, castedThis, WTFMove(promise), throwScope);
         if (distinguishingArg.isNumber())
             return jsTestObjPrototypeFunctionTestPromiseOverloadedFunction1Body(state, castedThis, WTFMove(promise), throwScope);
index 60fd522..197ecf9 100644 (file)
@@ -148,11 +148,11 @@ template<> EncodedJSValue JSC_HOST_CALL JSTestOverloadedConstructorsConstructor:
     }
     if (argsCount == 1) {
         JSValue distinguishingArg = state->uncheckedArgument(0);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSArrayBuffer::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSArrayBuffer>(vm))
             return constructJSTestOverloadedConstructors1(state);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSArrayBufferView::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSArrayBufferView>(vm))
             return constructJSTestOverloadedConstructors2(state);
-        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits(vm, JSBlob::info()))
+        if (distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JSBlob>(vm))
             return constructJSTestOverloadedConstructors3(state);
         if (distinguishingArg.isNumber())
             return constructJSTestOverloadedConstructors5(state);
index 731a6e8..398b7be 100644 (file)
@@ -159,7 +159,7 @@ JSValue CInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeMethod)
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    if (!asObject(runtimeMethod)->inherits(vm, CRuntimeMethod::info()))
+    if (!asObject(runtimeMethod)->inherits<CRuntimeMethod>(vm))
         return throwTypeError(exec, scope, ASCIILiteral("Attempt to invoke non-plug-in method on plug-in object."));
 
     CMethod* method = static_cast<CMethod*>(runtimeMethod->method());
index e82c557..ea2473d 100644 (file)
@@ -570,11 +570,11 @@ static void getListFromNSArray(ExecState *exec, NSArray *array, RootObject* root
         JSC::VM& vm = rootObject->globalObject()->vm();
         JSLockHolder lock(vm);
 
-        if (object->inherits(vm, JSHTMLElement::info())) {
+        if (object->inherits<JSHTMLElement>(vm)) {
             // Plugin elements cache the instance internally.
             if (ObjcInstance* instance = static_cast<ObjcInstance*>(pluginInstance(jsCast<JSHTMLElement*>(object)->wrapped())))
                 return instance->getObject();
-        } else if (object->inherits(vm, ObjCRuntimeObject::info())) {
+        } else if (object->inherits<ObjCRuntimeObject>(vm)) {
             ObjCRuntimeObject* runtimeObject = static_cast<ObjCRuntimeObject*>(object);
             ObjcInstance* instance = runtimeObject->getInternalObjCInstance();
             if (instance)
index 3fbae33..b7d24d4 100644 (file)
@@ -212,7 +212,7 @@ JSC::JSValue ObjcInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeM
     JSC::VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    if (!asObject(runtimeMethod)->inherits(vm, ObjCRuntimeMethod::info()))
+    if (!asObject(runtimeMethod)->inherits<ObjCRuntimeMethod>(vm))
         return throwTypeError(exec, scope, ASCIILiteral("Attempt to invoke non-plug-in method on plug-in object."));
 
     ObjcMethod *method = static_cast<ObjcMethod*>(runtimeMethod->method());
index 0a89c85..163c1da 100644 (file)
@@ -249,7 +249,7 @@ static EncodedJSValue JSC_HOST_CALL callObjCFallbackObject(ExecState* exec)
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     JSValue thisValue = exec->thisValue();
-    if (!thisValue.inherits(vm, ObjCRuntimeObject::info()))
+    if (!thisValue.inherits<ObjCRuntimeObject>(vm))
         return throwVMTypeError(exec, scope);
 
     JSValue result = jsUndefined();
index c35182b..67ee75d 100644 (file)
@@ -92,14 +92,14 @@ static EncodedJSValue JSC_HOST_CALL callRuntimeMethod(ExecState* exec)
     RefPtr<Instance> instance;
 
     JSValue thisValue = exec->thisValue();
-    if (thisValue.inherits(vm, RuntimeObject::info())) {
+    if (thisValue.inherits<RuntimeObject>(vm)) {
         RuntimeObject* runtimeObject = static_cast<RuntimeObject*>(asObject(thisValue));
         instance = runtimeObject->getInternalInstance();
         if (!instance) 
             return JSValue::encode(RuntimeObject::throwInvalidAccessError(exec, scope));
     } else {
         // Calling a runtime object of a plugin element?
-        if (thisValue.inherits(vm, JSHTMLElement::info()))
+        if (thisValue.inherits<JSHTMLElement>(vm))
             instance = pluginInstance(jsCast<JSHTMLElement*>(asObject(thisValue))->wrapped());
         if (!instance)
             return throwVMTypeError(exec, scope);
index 15f0a94..6a7284f 100644 (file)
@@ -224,7 +224,7 @@ JSValue RuntimeObject::defaultValue(const JSObject* object, ExecState* exec, Pre
 
 static EncodedJSValue JSC_HOST_CALL callRuntimeObject(ExecState* exec)
 {
-    ASSERT(exec->jsCallee()->inherits(exec->vm(), RuntimeObject::info()));
+    ASSERT(exec->jsCallee()->inherits<RuntimeObject>(exec->vm()));
     RefPtr<Instance> instance(static_cast<RuntimeObject*>(exec->jsCallee())->getInternalInstance());
     instance->begin();
     JSValue result = instance->invokeDefaultMethod(exec);
@@ -249,7 +249,7 @@ CallType RuntimeObject::getCallData(JSCell* cell, CallData& callData)
 static EncodedJSValue JSC_HOST_CALL callRuntimeConstructor(ExecState* exec)
 {
     JSObject* constructor = exec->jsCallee();
-    ASSERT(constructor->inherits(exec->vm(), RuntimeObject::info()));
+    ASSERT(constructor->inherits<RuntimeObject>(exec->vm()));
     RefPtr<Instance> instance(static_cast<RuntimeObject*>(exec->jsCallee())->getInternalInstance());
     instance->begin();
     ArgList args(exec);
index 555277b..9064b24 100644 (file)
@@ -47,13 +47,13 @@ using namespace JSC;
 JSValue WebInjectedScriptHost::subtype(ExecState* exec, JSValue value)
 {
     VM& vm = exec->vm();
-    if (value.inherits(vm, JSNode::info()))
+    if (value.inherits<JSNode>(vm))
         return jsNontrivialString(exec, ASCIILiteral("node"));
-    if (value.inherits(vm, JSNodeList::info()))
+    if (value.inherits<JSNodeList>(vm))
         return jsNontrivialString(exec, ASCIILiteral("array"));
-    if (value.inherits(vm, JSHTMLCollection::info()))
+    if (value.inherits<JSHTMLCollection>(vm))
         return jsNontrivialString(exec, ASCIILiteral("array"));
-    if (value.inherits(vm, JSDOMException::info()))
+    if (value.inherits<JSDOMException>(vm))
         return jsNontrivialString(exec, ASCIILiteral("error"));
 
     return jsUndefined();
@@ -185,7 +185,7 @@ JSValue WebInjectedScriptHost::getInternalProperties(VM& vm, ExecState* exec, JS
 
 bool WebInjectedScriptHost::isHTMLAllCollection(JSC::VM& vm, JSC::JSValue value)
 {
-    return value.inherits(vm, JSHTMLAllCollection::info());
+    return value.inherits<JSHTMLAllCollection>(vm);
 }
 
 } // namespace WebCore
index 89ea652..9a21313 100644 (file)
@@ -1,3 +1,20 @@
+2018-03-08  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [JSC] Add inherits<T>(VM&) leveraging JSCast fast path
+        https://bugs.webkit.org/show_bug.cgi?id=183429
+
+        Reviewed by Mark Lam.
+
+        * WebProcess/Plugins/Netscape/JSNPMethod.cpp:
+        (WebKit::callMethod):
+        * WebProcess/Plugins/Netscape/JSNPObject.cpp:
+        (WebKit::callNPJSObject):
+        (WebKit::constructWithConstructor):
+        * WebProcess/Plugins/Netscape/NPJSObject.cpp:
+        (WebKit::NPJSObject::create):
+        * WebProcess/WebPage/WebFrame.cpp:
+        (WebKit::WebFrame::counterValue):
+
 2018-03-08  Zan Dobersek  <zdobersek@igalia.com>
 
         Remove WebCore::TextureMapperAnimation as a special case in WebKit IPC
index e56088f..8f0d4df 100644 (file)
@@ -69,7 +69,7 @@ static EncodedJSValue JSC_HOST_CALL callMethod(ExecState* exec)
     JSValue thisValue = exec->thisValue();
 
     // Check if we're calling a method on the plug-in script object.
-    if (thisValue.inherits(vm, JSHTMLElement::info())) {
+    if (thisValue.inherits<JSHTMLElement>(vm)) {
         JSHTMLElement* element = jsCast<JSHTMLElement*>(asObject(thisValue));
 
         // Try to get the script object from the element
@@ -77,7 +77,7 @@ static EncodedJSValue JSC_HOST_CALL callMethod(ExecState* exec)
             thisValue = scriptObject;
     }
 
-    if (thisValue.inherits(vm, JSNPObject::info())) {
+    if (thisValue.inherits<JSNPObject>(vm)) {
         JSNPObject* jsNPObject = jsCast<JSNPObject*>(asObject(thisValue));
 
         return JSValue::encode(jsNPObject->callMethod(exec, jsNPMethod->npIdentifier()));
index 07a4e22..1fa5901 100644 (file)
@@ -241,7 +241,7 @@ JSValue JSNPObject::callConstructor(ExecState* exec)
 static EncodedJSValue JSC_HOST_CALL callNPJSObject(ExecState* exec)
 {
     JSObject* object = exec->jsCallee();
-    ASSERT(object->inherits(exec->vm(), JSNPObject::info()));
+    ASSERT(object->inherits<JSNPObject>(exec->vm()));
 
     return JSValue::encode(jsCast<JSNPObject*>(object)->callObject(exec));
 }
@@ -260,7 +260,7 @@ JSC::CallType JSNPObject::getCallData(JSC::JSCell* cell, JSC::CallData& callData
 static EncodedJSValue JSC_HOST_CALL constructWithConstructor(ExecState* exec)
 {
     JSObject* constructor = exec->jsCallee();
-    ASSERT(constructor->inherits(exec->vm(), JSNPObject::info()));
+    ASSERT(constructor->inherits<JSNPObject>(exec->vm()));
 
     return JSValue::encode(jsCast<JSNPObject*>(constructor)->callConstructor(exec));
 }
index 81ca70e..d1267d7 100644 (file)
@@ -49,7 +49,7 @@ namespace WebKit {
 NPJSObject* NPJSObject::create(VM& vm, NPRuntimeObjectMap* objectMap, JSObject* jsObject)
 {
     // We should never have a JSNPObject inside an NPJSObject.
-    ASSERT(!jsObject->inherits(vm, JSNPObject::info()));
+    ASSERT(!jsObject->inherits<JSNPObject>(vm));
 
     NPJSObject* npJSObject = toNPJSObject(createNPObject(0, npClass()));
     npJSObject->initialize(vm, objectMap, jsObject);
index afd3423..100f674 100644 (file)
@@ -738,7 +738,7 @@ JSValueRef WebFrame::jsWrapperForWorld(InjectedBundleFileHandle* fileHandle, Inj
 
 String WebFrame::counterValue(JSObjectRef element)
 {
-    if (!toJS(element)->inherits(*toJS(element)->vm(), JSElement::info()))
+    if (!toJS(element)->inherits<JSElement>(*toJS(element)->vm()))
         return String();
 
     return counterValueForElement(&jsCast<JSElement*>(toJS(element))->wrapped());
index 64691f0..e002682 100644 (file)
@@ -1,3 +1,20 @@
+2018-03-08  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [JSC] Add inherits<T>(VM&) leveraging JSCast fast path
+        https://bugs.webkit.org/show_bug.cgi?id=183429
+
+        Reviewed by Mark Lam.
+
+        * DOM/DOM.mm:
+        (+[DOMNode _nodeFromJSWrapper:]):
+        * Plugins/Hosted/NetscapePluginInstanceProxy.mm:
+        (WebKit::NetscapePluginInstanceProxy::retainLocalObject):
+        (WebKit::NetscapePluginInstanceProxy::releaseLocalObject):
+        * Plugins/Hosted/ProxyInstance.mm:
+        (WebKit::ProxyInstance::invokeMethod):
+        * WebView/WebView.mm:
+        (aeDescFromJSValue):
+
 2018-03-08  Tim Horton  <timothy_horton@apple.com>
 
         Stop linking ApplicationServices directly
index 59f1363..e7ce631 100644 (file)
@@ -530,7 +530,7 @@ id <DOMEventTarget> kit(EventTarget* target)
 + (id)_nodeFromJSWrapper:(JSObjectRef)jsWrapper
 {
     JSObject* object = toJS(jsWrapper);
-    if (!object->inherits(*object->vm(), JSNode::info()))
+    if (!object->inherits<JSNode>(*object->vm()))
         return nil;
     return kit(&jsCast<JSNode*>(object)->wrapped());
 }
index 851574f..6f2d259 100644 (file)
@@ -1453,7 +1453,7 @@ void NetscapePluginInstanceProxy::demarshalValues(ExecState* exec, data_t values
 
 void NetscapePluginInstanceProxy::retainLocalObject(JSC::JSValue value)
 {
-    if (!value.isObject() || value.inherits(*value.getObject()->vm(), ProxyRuntimeObject::info()))
+    if (!value.isObject() || value.inherits<ProxyRuntimeObject>(*value.getObject()->vm()))
         return;
 
     m_localObjects.retain(asObject(value));
@@ -1461,7 +1461,7 @@ void NetscapePluginInstanceProxy::retainLocalObject(JSC::JSValue value)
 
 void NetscapePluginInstanceProxy::releaseLocalObject(JSC::JSValue value)
 {
-    if (!value.isObject() || value.inherits(*value.getObject()->vm(), ProxyRuntimeObject::info()))
+    if (!value.isObject() || value.inherits<ProxyRuntimeObject>(*value.getObject()->vm()))
         return;
 
     m_localObjects.release(asObject(value));
index 26ab3eb..3687bc1 100644 (file)
@@ -223,7 +223,7 @@ JSValue ProxyInstance::invokeMethod(ExecState* exec, JSC::RuntimeMethod* runtime
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    if (!asObject(runtimeMethod)->inherits(vm, ProxyRuntimeMethod::info()))
+    if (!asObject(runtimeMethod)->inherits<ProxyRuntimeMethod>(vm))
         return throwTypeError(exec, scope, ASCIILiteral("Attempt to invoke non-plug-in method on plug-in object."));
 
     ProxyMethod* method = static_cast<ProxyMethod*>(runtimeMethod->method());
index ec26b2b..435a597 100644 (file)
@@ -7637,7 +7637,7 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSC::JSValue j
     }
     if (jsValue.isObject()) {
         JSObject* object = jsValue.getObject();
-        if (object->inherits(vm, DateInstance::info())) {
+        if (object->inherits<DateInstance>(vm)) {
             DateInstance* date = static_cast<DateInstance*>(object);
             double ms = date->internalNumber();
             if (!std::isnan(ms)) {
@@ -7646,7 +7646,7 @@ static NSAppleEventDescriptor* aeDescFromJSValue(ExecState* exec, JSC::JSValue j
                 if (noErr == UCConvertCFAbsoluteTimeToLongDateTime(utcSeconds, &ldt))
                     return [NSAppleEventDescriptor descriptorWithDescriptorType:typeLongDateTime bytes:&ldt length:sizeof(ldt)];
             }
-        } else if (object->inherits(vm, JSArray::info())) {
+        } else if (object->inherits<JSArray>(vm)) {
             static NeverDestroyed<HashSet<JSObject*>> visitedElems;
             if (visitedElems.get().add(object).isNewEntry) {
                 JSArray* array = static_cast<JSArray*>(object);
index 21dc785..5aab523 100644 (file)
@@ -1,3 +1,13 @@
+2018-03-08  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [JSC] Add inherits<T>(VM&) leveraging JSCast fast path
+        https://bugs.webkit.org/show_bug.cgi?id=183429
+
+        Reviewed by Mark Lam.
+
+        * WebFrame.cpp:
+        (WebFrame::stringByEvaluatingJavaScriptInScriptWorld):
+
 2018-03-08  Tim Horton  <timothy_horton@apple.com>
 
         Stop linking ApplicationServices directly
index 937a257..87dc90b 100644 (file)
@@ -2002,7 +2002,7 @@ HRESULT WebFrame::stringByEvaluatingJavaScriptInScriptWorld(IWebScriptWorld* iWo
 
     // The global object is probably a proxy object? - if so, we know how to use this!
     JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
-    if (globalObjectObj->inherits(*globalObjectObj->vm(), JSDOMWindowProxy::info()))
+    if (globalObjectObj->inherits<JSDOMWindowProxy>(*globalObjectObj->vm()))
         anyWorldGlobalObject = static_cast<JSDOMWindowProxy*>(globalObjectObj)->window();
 
     // Get the frame frome the global object we've settled on.