Changeset 180467 in webkit


Ignore:
Timestamp:
Feb 20, 2015 4:36:27 PM (9 years ago)
Author:
mark.lam@apple.com
Message:

Refactor JSWrapperMap.mm to defer creation of the ObjC JSValue until the latest possible moment.
<https://webkit.org/b/141856>

Reviewed by Geoffrey Garen.

  1. Make JSObjCClassInfo's -constructor and -wrapperForObject return a JSC::JSObject* just like -prototype.
  2. Defer the creation of the ObjC JSValue from JSC::JSObject* until the latest moment when it is needed. This allows us to not have to keep converting back to a JSC::JSObject* in intermediate code.
  • API/JSWrapperMap.mm:

(makeWrapper):
(objectWithCustomBrand):
(constructorWithCustomBrand):
(allocateConstructorForCustomClass):
(-[JSObjCClassInfo allocateConstructorAndPrototype]):
(-[JSObjCClassInfo wrapperForObject:]):
(-[JSObjCClassInfo constructor]):
(-[JSWrapperMap jsWrapperForObject:]):

Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSWrapperMap.mm

    r180452 r180467  
    109109}
    110110
    111 static JSObjectRef makeWrapper(JSContextRef ctx, JSClassRef jsClass, id wrappedObject)
     111static JSC::JSObject* makeWrapper(JSContextRef ctx, JSClassRef jsClass, id wrappedObject)
    112112{
    113113    JSC::ExecState* exec = toJS(ctx);
     
    120120        object->setPrototype(exec->vm(), prototype);
    121121
    122     return toRef(object);
     122    return object;
    123123}
    124124
     
    126126// other than that it has a native brand set that will be displayed by the default
    127127// Object.prototype.toString conversion.
    128 static JSValue *objectWithCustomBrand(JSContext *context, NSString *brand, Class cls = 0)
     128static JSC::JSObject *objectWithCustomBrand(JSContext *context, NSString *brand, Class cls = 0)
    129129{
    130130    JSClassDefinition definition;
     
    132132    definition.className = [brand UTF8String];
    133133    JSClassRef classRef = JSClassCreate(&definition);
    134     JSObjectRef result = makeWrapper([context JSGlobalContextRef], classRef, cls);
     134    JSC::JSObject* result = makeWrapper([context JSGlobalContextRef], classRef, cls);
    135135    JSClassRelease(classRef);
    136     return [JSValue valueWithJSValueRef:result inContext:context];
    137 }
    138 
    139 static JSValue *constructorWithCustomBrand(JSContext *context, NSString *brand, Class cls)
     136    return result;
     137}
     138
     139static JSC::JSObject *constructorWithCustomBrand(JSContext *context, NSString *brand, Class cls)
    140140{
    141141    JSClassDefinition definition;
     
    144144    definition.hasInstance = constructorHasInstance;
    145145    JSClassRef classRef = JSClassCreate(&definition);
    146     JSObjectRef result = makeWrapper([context JSGlobalContextRef], classRef, cls);
     146    JSC::JSObject* result = makeWrapper([context JSGlobalContextRef], classRef, cls);
    147147    JSClassRelease(classRef);
    148     return [JSValue valueWithJSValueRef:result inContext:context];
     148    return result;
    149149}
    150150
     
    366366
    367367- (id)initWithContext:(JSContext *)context forClass:(Class)cls;
    368 - (JSValue *)wrapperForObject:(id)object;
    369 - (JSValue *)constructor;
     368- (JSC::JSObject *)wrapperForObject:(id)object;
     369- (JSC::JSObject *)constructor;
    370370- (JSC::JSObject *)prototype;
    371371
     
    398398}
    399399
    400 static JSValue *allocateConstructorForCustomClass(JSContext *context, const char* className, Class cls)
     400static JSC::JSObject* allocateConstructorForCustomClass(JSContext *context, const char* className, Class cls)
    401401{
    402402    if (!supportsInitMethodConstructors())
     
    445445
    446446        JSObjectRef method = objCCallbackFunctionForInit(context, cls, initProtocol, initMethod, types);
    447         return [JSValue valueWithJSValueRef:method inContext:context];
     447        return toJS(method);
    448448    }
    449449    return constructorWithCustomBrand(context, [NSString stringWithFormat:@"%sConstructor", className], cls);
     
    458458    ASSERT(!m_constructor || !m_prototype);
    459459    ASSERT((m_class == [NSObject class]) == !superClassInfo);
     460
     461    JSC::JSObject* jsPrototype = m_prototype.get();
     462    JSC::JSObject* jsConstructor = m_constructor.get();
     463
    460464    if (!superClassInfo) {
    461465        JSContextRef cContext = [m_context JSGlobalContextRef];
    462466        JSValue *constructor = m_context[@"Object"];
    463         if (!m_constructor)
    464             m_constructor = toJS(JSValueToObject(cContext, valueInternalValue(constructor), 0));
    465 
    466         if (!m_prototype) {
     467        if (!jsConstructor)
     468            jsConstructor = toJS(JSValueToObject(cContext, valueInternalValue(constructor), 0));
     469
     470        if (!jsPrototype) {
    467471            JSValue *prototype = constructor[@"prototype"];
    468             m_prototype = toJS(JSValueToObject(cContext, valueInternalValue(prototype), 0));
     472            jsPrototype = toJS(JSValueToObject(cContext, valueInternalValue(prototype), 0));
    469473        }
    470474    } else {
     
    472476
    473477        // Create or grab the prototype/constructor pair.
    474         JSValue *prototype;
    475         JSValue *constructor;
    476         if (m_prototype)
    477             prototype = [JSValue valueWithJSValueRef:toRef(m_prototype.get()) inContext:m_context];
    478         else
    479             prototype = objectWithCustomBrand(m_context, [NSString stringWithFormat:@"%sPrototype", className]);
    480 
    481         if (m_constructor)
    482             constructor = [JSValue valueWithJSValueRef:toRef(m_constructor.get()) inContext:m_context];
    483         else
    484             constructor = allocateConstructorForCustomClass(m_context, className, m_class);
    485 
    486         JSContextRef cContext = [m_context JSGlobalContextRef];
    487         m_prototype = toJS(JSValueToObject(cContext, valueInternalValue(prototype), 0));
    488         m_constructor = toJS(JSValueToObject(cContext, valueInternalValue(constructor), 0));
    489 
     478        if (!jsPrototype)
     479            jsPrototype = objectWithCustomBrand(m_context, [NSString stringWithFormat:@"%sPrototype", className]);
     480
     481        if (!jsConstructor)
     482            jsConstructor = allocateConstructorForCustomClass(m_context, className, m_class);
     483
     484        JSValue* prototype = [JSValue valueWithJSValueRef:toRef(jsPrototype) inContext:m_context];
     485        JSValue* constructor = [JSValue valueWithJSValueRef:toRef(jsConstructor) inContext:m_context];
    490486        putNonEnumerable(prototype, @"constructor", constructor);
    491487        putNonEnumerable(constructor, @"prototype", prototype);
     
    499495        // Set [Prototype].
    500496        JSC::JSObject* superClassPrototype = [superClassInfo prototype];
    501         JSObjectSetPrototype([m_context JSGlobalContextRef], toRef(m_prototype.get()), toRef(superClassPrototype));
    502     }
    503     return ConstructorPrototypePair(m_constructor.get(), m_prototype.get());
    504 }
    505 
    506 - (JSValue *)wrapperForObject:(id)object
     497        JSObjectSetPrototype([m_context JSGlobalContextRef], toRef(jsPrototype), toRef(superClassPrototype));
     498    }
     499
     500    m_prototype = jsPrototype;
     501    m_constructor = jsConstructor;
     502    return ConstructorPrototypePair(jsConstructor, jsPrototype);
     503}
     504
     505- (JSC::JSObject*)wrapperForObject:(id)object
    507506{
    508507    ASSERT([object isKindOfClass:m_class]);
     
    514513            putNonEnumerable(constructor, @"prototype", prototype);
    515514            putNonEnumerable(prototype, @"constructor", constructor);
    516             return constructor;
     515            return toJS(method);
    517516        }
    518517    }
     
    520519    JSC::JSObject* prototype = [self prototype];
    521520
    522     JSObjectRef wrapper = makeWrapper([m_context JSGlobalContextRef], m_classRef, object);
    523     JSObjectSetPrototype([m_context JSGlobalContextRef], wrapper, toRef(prototype));
    524     return [JSValue valueWithJSValueRef:wrapper inContext:m_context];
    525 }
    526 
    527 - (JSValue *)constructor
     521    JSC::JSObject* wrapper = makeWrapper([m_context JSGlobalContextRef], m_classRef, object);
     522    JSObjectSetPrototype([m_context JSGlobalContextRef], toRef(wrapper), toRef(prototype));
     523    return wrapper;
     524}
     525
     526- (JSC::JSObject*)constructor
    528527{
    529528    JSC::JSObject* constructor = m_constructor.get();
     
    531530        constructor = [self allocateConstructorAndPrototype].first;
    532531    ASSERT(!!constructor);
    533     return [JSValue valueWithJSValueRef:toRef(constructor) inContext:m_context];
     532    return constructor;
    534533}
    535534
     
    596595        return [JSValue valueWithJSValueRef:toRef(jsWrapper) inContext:m_context];
    597596
    598     JSValue *wrapper;
    599597    if (class_isMetaClass(object_getClass(object)))
    600         wrapper = [[self classInfoForClass:(Class)object] constructor];
     598        jsWrapper = [[self classInfoForClass:(Class)object] constructor];
    601599    else {
    602600        JSObjCClassInfo* classInfo = [self classInfoForClass:[object class]];
    603         wrapper = [classInfo wrapperForObject:object];
     601        jsWrapper = [classInfo wrapperForObject:object];
    604602    }
    605603
     
    609607    // (2) A long lived object may rack up many JSValues. When the contexts are released these will unprotect the associated JavaScript objects,
    610608    //     but still, would probably nicer if we made it so that only one associated object was required, broadcasting object dealloc.
    611     JSC::ExecState* exec = toJS([m_context JSGlobalContextRef]);
    612     jsWrapper = toJS(exec, valueInternalValue(wrapper)).toObject(exec);
    613609    m_cachedJSWrappers.set(object, jsWrapper);
    614     return wrapper;
     610    return [JSValue valueWithJSValueRef:toRef(jsWrapper) inContext:m_context];
    615611}
    616612
  • trunk/Source/JavaScriptCore/ChangeLog

    r180461 r180467  
     12015-02-20  Mark Lam  <mark.lam@apple.com>
     2
     3        Refactor JSWrapperMap.mm to defer creation of the ObjC JSValue until the latest possible moment.
     4        <https://webkit.org/b/141856>
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        1. Make JSObjCClassInfo's -constructor and -wrapperForObject return a
     9           JSC::JSObject* just like -prototype.
     10        2. Defer the creation of the ObjC JSValue from JSC::JSObject* until
     11           the latest moment when it is needed.  This allows us to not have to
     12           keep converting back to a JSC::JSObject* in intermediate code.
     13
     14        * API/JSWrapperMap.mm:
     15        (makeWrapper):
     16        (objectWithCustomBrand):
     17        (constructorWithCustomBrand):
     18        (allocateConstructorForCustomClass):
     19        (-[JSObjCClassInfo allocateConstructorAndPrototype]):
     20        (-[JSObjCClassInfo wrapperForObject:]):
     21        (-[JSObjCClassInfo constructor]):
     22        (-[JSWrapperMap jsWrapperForObject:]):
     23
    1242015-02-20  Filip Pizlo  <fpizlo@apple.com>
    225
Note: See TracChangeset for help on using the changeset viewer.