Changeset 180452 in webkit
- Timestamp:
- Feb 20, 2015 1:51:37 PM (9 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/API/JSWrapperMap.mm
r177091 r180452 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 365 365 } 366 366 367 - (id)initWithContext:(JSContext *)context forClass:(Class)cls superClassInfo:(JSObjCClassInfo*)superClassInfo;367 - (id)initWithContext:(JSContext *)context forClass:(Class)cls; 368 368 - (JSValue *)wrapperForObject:(id)object; 369 369 - (JSValue *)constructor; 370 - (JSC::JSObject *)prototype; 370 371 371 372 @end … … 373 374 @implementation JSObjCClassInfo 374 375 375 - (id)initWithContext:(JSContext *)context forClass:(Class)cls superClassInfo:(JSObjCClassInfo*)superClassInfo376 - (id)initWithContext:(JSContext *)context forClass:(Class)cls 376 377 { 377 378 self = [super init]; … … 387 388 definition.className = className; 388 389 m_classRef = JSClassCreate(&definition); 389 390 [self allocateConstructorAndPrototypeWithSuperClassInfo:superClassInfo];391 390 392 391 return self; … … 451 450 } 452 451 453 - (void)allocateConstructorAndPrototypeWithSuperClassInfo:(JSObjCClassInfo*)superClassInfo 454 { 452 typedef std::pair<JSC::JSObject*, JSC::JSObject*> ConstructorPrototypePair; 453 454 - (ConstructorPrototypePair)allocateConstructorAndPrototype 455 { 456 JSObjCClassInfo* superClassInfo = [m_context.wrapperMap classInfoForClass:class_getSuperclass(m_class)]; 457 455 458 ASSERT(!m_constructor || !m_prototype); 456 459 ASSERT((m_class == [NSObject class]) == !superClassInfo); … … 466 469 } 467 470 } else { 468 // We need to hold a reference to the superclass prototype here on the stack469 // to that it won't get GC'ed while we do allocations between now and when we470 // set it in this class' prototype below.471 JSC::JSObject* superClassPrototype = superClassInfo->m_prototype.get();472 473 471 const char* className = class_getName(m_class); 474 472 … … 500 498 501 499 // Set [Prototype]. 500 JSC::JSObject* superClassPrototype = [superClassInfo prototype]; 502 501 JSObjectSetPrototype([m_context JSGlobalContextRef], toRef(m_prototype.get()), toRef(superClassPrototype)); 503 502 } 504 } 505 506 - (void)reallocateConstructorAndOrPrototype 507 { 508 [self allocateConstructorAndPrototypeWithSuperClassInfo:[m_context.wrapperMap classInfoForClass:class_getSuperclass(m_class)]]; 509 // We should not add any code here that can trigger a GC or the prototype and 510 // constructor that we just created may be collected before they can be used. 503 return ConstructorPrototypePair(m_constructor.get(), m_prototype.get()); 511 504 } 512 505 … … 525 518 } 526 519 527 if (!m_prototype) 528 [self reallocateConstructorAndOrPrototype]; 529 ASSERT(!!m_prototype); 530 // We need to hold a reference to the prototype here on the stack to that it won't 531 // get GC'ed while we create the wrapper below. 532 JSC::JSObject* prototype = m_prototype.get(); 520 JSC::JSObject* prototype = [self prototype]; 533 521 534 522 JSObjectRef wrapper = makeWrapper([m_context JSGlobalContextRef], m_classRef, object); … … 539 527 - (JSValue *)constructor 540 528 { 541 if (!m_constructor) 542 [self reallocateConstructorAndOrPrototype]; 543 ASSERT(!!m_constructor); 544 // If we need to add any code here in the future that can trigger a GC, we should 545 // cache the constructor pointer in a stack local var first so that it is protected 546 // from the GC until it gets used below. 547 return [JSValue valueWithJSValueRef:toRef(m_constructor.get()) inContext:m_context]; 529 JSC::JSObject* constructor = m_constructor.get(); 530 if (!constructor) 531 constructor = [self allocateConstructorAndPrototype].first; 532 ASSERT(!!constructor); 533 return [JSValue valueWithJSValueRef:toRef(constructor) inContext:m_context]; 534 } 535 536 - (JSC::JSObject*)prototype 537 { 538 JSC::JSObject* prototype = m_prototype.get(); 539 if (!prototype) 540 prototype = [self allocateConstructorAndPrototype].second; 541 ASSERT(!!prototype); 542 return prototype; 548 543 } 549 544 … … 592 587 return m_classMap[cls] = [self classInfoForClass:class_getSuperclass(cls)]; 593 588 594 return m_classMap[cls] = [[[JSObjCClassInfo alloc] initWithContext:m_context forClass:cls superClassInfo:[self classInfoForClass:class_getSuperclass(cls)]] autorelease];589 return m_classMap[cls] = [[[JSObjCClassInfo alloc] initWithContext:m_context forClass:cls] autorelease]; 595 590 } 596 591 -
trunk/Source/JavaScriptCore/API/tests/testapi.mm
r179753 r180452 1 1 /* 2 * Copyright (C) 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 29 29 #import "DateTests.h" 30 30 #import "JSExportTests.h" 31 #import "Regress141809.h" 31 32 32 33 #import <pthread.h> … … 1432 1433 runDateTests(); 1433 1434 runJSExportTests(); 1435 runRegress141809(); 1434 1436 } 1435 1437 -
trunk/Source/JavaScriptCore/ChangeLog
r180441 r180452 1 2015-02-20 Mark Lam <mark.lam@apple.com> 2 3 [JSObjCClassInfo reallocateConstructorAndOrPrototype] should also reallocate super class prototype chain. 4 <https://webkit.org/b/141809> 5 6 Reviewed by Geoffrey Garen. 7 8 A ObjC class that implement the JSExport protocol will have a JS prototype 9 chain and constructor automatically synthesized for its JS wrapper object. 10 However, if there are no more instances of that ObjC class reachable by a 11 JS GC root scan, then its synthesized prototype chain and constructors may 12 be released by the GC. If a new instance of that ObjC class is subsequently 13 instantiated, then [JSObjCClassInfo reallocateConstructorAndOrPrototype] 14 should re-construct the prototype chain and constructor (if they were 15 previously released). However, the current implementation only 16 re-constructs the immediate prototype, but not every other prototype 17 object upstream in the prototype chain. 18 19 To fix this, we do the following: 20 1. We no longer allocate the JSObjCClassInfo's prototype and constructor 21 eagerly. Hence, -initWithContext:forClass: will no longer call 22 -allocateConstructorAndPrototypeWithSuperClassInfo:. 23 2. Instead, we'll always access the prototype and constructor thru 24 accessor methods. The accessor methods will call 25 -allocateConstructorAndPrototype: if needed. 26 3. -allocateConstructorAndPrototype: will fetch the needed superClassInfo 27 from the JSWrapperMap itself. This makes it so that we no longer 28 need to pass the superClassInfo all over. 29 4. -allocateConstructorAndPrototype: will get the super class prototype 30 by invoking -prototype: on the superClassInfo, thereby allowing the 31 super class to allocate its prototype and constructor if needed and 32 fixing the issue in this bug. 33 34 5. Also removed the GC warning comments, and ensured that needed JS 35 objects are kept alive by having a local var pointing to it from the 36 stack (which makes a GC root). 37 38 * API/JSWrapperMap.mm: 39 (-[JSObjCClassInfo initWithContext:forClass:]): 40 (-[JSObjCClassInfo allocateConstructorAndPrototype]): 41 (-[JSObjCClassInfo wrapperForObject:]): 42 (-[JSObjCClassInfo constructor]): 43 (-[JSObjCClassInfo prototype]): 44 (-[JSWrapperMap classInfoForClass:]): 45 (-[JSObjCClassInfo initWithContext:forClass:superClassInfo:]): Deleted. 46 (-[JSObjCClassInfo allocateConstructorAndPrototypeWithSuperClassInfo:]): Deleted. 47 (-[JSObjCClassInfo reallocateConstructorAndOrPrototype]): Deleted. 48 * API/tests/Regress141809.h: Added. 49 * API/tests/Regress141809.mm: Added. 50 (-[TestClassB name]): 51 (-[TestClassC name]): 52 (runRegress141809): 53 * API/tests/testapi.mm: 54 * JavaScriptCore.xcodeproj/project.pbxproj: 55 1 56 2015-02-20 Alexey Proskuryakov <ap@apple.com> 2 57 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r180279 r180452 1613 1613 FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861E182B7A0400F6D851 /* Breakpoint.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1614 1614 FEA08621182B7A0400F6D851 /* DebuggerPrimitives.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1615 FEB51F6C1A97B688001F921C /* Regress141809.mm in Sources */ = {isa = PBXBuildFile; fileRef = FEB51F6B1A97B688001F921C /* Regress141809.mm */; }; 1615 1616 FEB58C14187B8B160098EF0B /* ErrorHandlingScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEB58C12187B8B160098EF0B /* ErrorHandlingScope.cpp */; }; 1616 1617 FEB58C15187B8B160098EF0B /* ErrorHandlingScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FEB58C13187B8B160098EF0B /* ErrorHandlingScope.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 3346 3347 FEA0861E182B7A0400F6D851 /* Breakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakpoint.h; sourceTree = "<group>"; }; 3347 3348 FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerPrimitives.h; sourceTree = "<group>"; }; 3349 FEB51F6A1A97B688001F921C /* Regress141809.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Regress141809.h; path = API/tests/Regress141809.h; sourceTree = "<group>"; }; 3350 FEB51F6B1A97B688001F921C /* Regress141809.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = Regress141809.mm; path = API/tests/Regress141809.mm; sourceTree = "<group>"; }; 3348 3351 FEB58C12187B8B160098EF0B /* ErrorHandlingScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ErrorHandlingScope.cpp; sourceTree = "<group>"; }; 3349 3352 FEB58C13187B8B160098EF0B /* ErrorHandlingScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ErrorHandlingScope.h; sourceTree = "<group>"; }; … … 3716 3719 C2181FC018A948FB0025A235 /* JSExportTests.h */, 3717 3720 C2181FC118A948FB0025A235 /* JSExportTests.mm */, 3721 FEB51F6A1A97B688001F921C /* Regress141809.h */, 3722 FEB51F6B1A97B688001F921C /* Regress141809.mm */, 3718 3723 144005170A531CB50005F061 /* minidom */, 3719 3724 14BD5A2D0A3E91F600BAF59C /* testapi.c */, … … 6736 6741 files = ( 6737 6742 C29ECB031804D0ED00D2CBB4 /* CurrentThisInsideBlockGetterTest.mm in Sources */, 6743 FEB51F6C1A97B688001F921C /* Regress141809.mm in Sources */, 6738 6744 C20328201981979D0088B499 /* CustomGlobalObjectClassTest.c in Sources */, 6739 6745 C288B2DE18A54D3E007BE40B /* DateTests.mm in Sources */,
Note: See TracChangeset
for help on using the changeset viewer.