source: webkit/trunk/JavaScriptCore/API/JSContextRef.cpp@ 54402

Last change on this file since 54402 was 53460, checked in by [email protected], 15 years ago

JavaScriptCore: REGRESSION (52082): Crash on worker thread when reloading http://radnan.public.iastate.edu/procedural/
https://bugs.webkit.org/show_bug.cgi?id=33826

Reviewed by Oliver Hunt.

This bug was caused by a GC-protected object being destroyed early by
Heap::destroy. Clients of the GC protect APIs (reasonably) expect pointers
to GC-protected memory to be valid.

The solution is to do two passes of tear-down in Heap::destroy. The first
pass tears down all unprotected objects. The second pass ASSERTs that all
previously protected objects are now unprotected, and then tears down
all perviously protected objects. These two passes simulate the two passes
that would have been required to free a protected object during normal GC.

  • API/JSContextRef.cpp: Removed some ASSERTs that have moved into Heap.
  • runtime/Collector.cpp:

(JSC::Heap::destroy): Moved ASSERTs to here.
(JSC::Heap::freeBlock): Tidied up the use of didShrink by moving its
setter to the function that does the shrinking.
(JSC::Heap::freeBlocks): Implemented above algorithm.
(JSC::Heap::shrinkBlocks): Tidied up the use of didShrink.

WebCore: REGRESSION (52082): Crash on worker thread when reloading http://radnan.public.iastate.edu/procedural/
https://bugs.webkit.org/show_bug.cgi?id=33826

Reviewed by Oliver Hunt.

Test: fast/workers/worker-gc2.html

  • bindings/js/WorkerScriptController.cpp:

(WebCore::WorkerScriptController::~WorkerScriptController): Removed some
ASSERTs that have moved to JavaScriptCore.

LayoutTests: REGRESSION (52082): Crash on worker thread when reloading http://radnan.public.iastate.edu/procedural/
https://bugs.webkit.org/show_bug.cgi?id=33826

Reviewed by Oliver Hunt.

Added a test for this edge case.

  • fast/workers/resources/worker-gc2.js: Added.

(Dummy):

  • fast/workers/worker-gc2.html: Added.
  • Property svn:eol-style set to native
File size: 5.2 KB
Line 
1/*
2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "JSContextRef.h"
28#include "JSContextRefPrivate.h"
29
30#include "APICast.h"
31#include "InitializeThreading.h"
32#include "JSCallbackObject.h"
33#include "JSClassRef.h"
34#include "JSGlobalObject.h"
35#include "JSObject.h"
36#include <wtf/Platform.h>
37
38#if OS(DARWIN)
39#include <mach-o/dyld.h>
40
41static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500; // 528.5.0
42#endif
43
44using namespace JSC;
45
46JSContextGroupRef JSContextGroupCreate()
47{
48 initializeThreading();
49 return toRef(JSGlobalData::createNonDefault().releaseRef());
50}
51
52JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group)
53{
54 toJS(group)->ref();
55 return group;
56}
57
58void JSContextGroupRelease(JSContextGroupRef group)
59{
60 toJS(group)->deref();
61}
62
63JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
64{
65 initializeThreading();
66#if OS(DARWIN)
67 // When running on Tiger or Leopard, or if the application was linked before JSGlobalContextCreate was changed
68 // to use a unique JSGlobalData, we use a shared one for compatibility.
69#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
70 if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) {
71#else
72 {
73#endif
74 JSLock lock(LockForReal);
75 return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass);
76 }
77#endif // OS(DARWIN)
78
79 return JSGlobalContextCreateInGroup(0, globalObjectClass);
80}
81
82JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClassRef globalObjectClass)
83{
84 initializeThreading();
85
86 JSLock lock(LockForReal);
87 RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createNonDefault();
88
89 APIEntryShim entryShim(globalData.get(), false);
90
91#if ENABLE(JSC_MULTIPLE_THREADS)
92 globalData->makeUsableFromMultipleThreads();
93#endif
94
95 if (!globalObjectClass) {
96 JSGlobalObject* globalObject = new (globalData.get()) JSGlobalObject;
97 return JSGlobalContextRetain(toGlobalRef(globalObject->globalExec()));
98 }
99
100 JSGlobalObject* globalObject = new (globalData.get()) JSCallbackObject<JSGlobalObject>(globalObjectClass);
101 ExecState* exec = globalObject->globalExec();
102 JSValue prototype = globalObjectClass->prototype(exec);
103 if (!prototype)
104 prototype = jsNull();
105 globalObject->resetPrototype(prototype);
106 return JSGlobalContextRetain(toGlobalRef(exec));
107}
108
109JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx)
110{
111 ExecState* exec = toJS(ctx);
112 APIEntryShim entryShim(exec);
113
114 JSGlobalData& globalData = exec->globalData();
115 gcProtect(exec->dynamicGlobalObject());
116 globalData.ref();
117 return ctx;
118}
119
120void JSGlobalContextRelease(JSGlobalContextRef ctx)
121{
122 ExecState* exec = toJS(ctx);
123 APIEntryShim entryShim(exec, false);
124
125 gcUnprotect(exec->dynamicGlobalObject());
126
127 JSGlobalData& globalData = exec->globalData();
128 if (globalData.refCount() == 2) { // One reference is held by JSGlobalObject, another added by JSGlobalContextRetain().
129 // The last reference was released, this is our last chance to collect.
130 globalData.heap.destroy();
131 } else
132 globalData.heap.collectAllGarbage();
133
134 globalData.deref();
135}
136
137JSObjectRef JSContextGetGlobalObject(JSContextRef ctx)
138{
139 ExecState* exec = toJS(ctx);
140 APIEntryShim entryShim(exec);
141
142 // It is necessary to call toThisObject to get the wrapper object when used with WebCore.
143 return toRef(exec->lexicalGlobalObject()->toThisObject(exec));
144}
145
146JSContextGroupRef JSContextGetGroup(JSContextRef ctx)
147{
148 ExecState* exec = toJS(ctx);
149 return toRef(&exec->globalData());
150}
151
152JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx)
153{
154 ExecState* exec = toJS(ctx);
155 APIEntryShim entryShim(exec);
156
157 return toGlobalRef(exec->lexicalGlobalObject()->globalExec());
158}
Note: See TracBrowser for help on using the repository browser.