Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
bc45b43a
Commit
bc45b43a
authored
Dec 12, 2023
by
Gabriel Ivăncescu
Committed by
Alexandre Julliard
Jan 22, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
jscript: Make the garbage collector thread-wide rather than per-ctx.
Signed-off-by:
Gabriel Ivăncescu
<
gabrielopcode@gmail.com
>
parent
39c7950a
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
38 additions
and
32 deletions
+38
-32
dispex.c
dlls/jscript/dispex.c
+16
-15
jscript.c
dlls/jscript/jscript.c
+3
-9
jscript.h
dlls/jscript/jscript.h
+7
-5
jscript_main.c
dlls/jscript/jscript_main.c
+9
-0
set.c
dlls/jscript/set.c
+3
-3
No files found.
dlls/jscript/dispex.c
View file @
bc45b43a
...
...
@@ -783,6 +783,7 @@ HRESULT gc_run(script_ctx_t *ctx)
struct
chunk
*
next
;
LONG
ref
[
1020
];
}
*
head
,
*
chunk
;
struct
thread_data
*
thread_data
=
ctx
->
thread_data
;
jsdisp_t
*
obj
,
*
obj2
,
*
link
,
*
link2
;
dispex_prop_t
*
prop
,
*
props_end
;
struct
gc_ctx
gc_ctx
=
{
0
};
...
...
@@ -791,7 +792,7 @@ HRESULT gc_run(script_ctx_t *ctx)
struct
list
*
iter
;
/* Prevent recursive calls from side-effects during unlinking (e.g. CollectGarbage from host object's Release) */
if
(
ctx
->
gc_is_unlinking
)
if
(
thread_data
->
gc_is_unlinking
)
return
S_OK
;
if
(
!
(
head
=
malloc
(
sizeof
(
*
head
))))
...
...
@@ -800,7 +801,7 @@ HRESULT gc_run(script_ctx_t *ctx)
chunk
=
head
;
/* 1. Save actual refcounts and decrease them speculatively as-if we unlinked the objects */
LIST_FOR_EACH_ENTRY
(
obj
,
&
ctx
->
objects
,
jsdisp_t
,
entry
)
{
LIST_FOR_EACH_ENTRY
(
obj
,
&
thread_data
->
objects
,
jsdisp_t
,
entry
)
{
if
(
chunk_idx
==
ARRAY_SIZE
(
chunk
->
ref
))
{
if
(
!
(
chunk
->
next
=
malloc
(
sizeof
(
*
chunk
))))
{
do
{
...
...
@@ -815,7 +816,7 @@ HRESULT gc_run(script_ctx_t *ctx)
}
chunk
->
ref
[
chunk_idx
++
]
=
obj
->
ref
;
}
LIST_FOR_EACH_ENTRY
(
obj
,
&
ctx
->
objects
,
jsdisp_t
,
entry
)
{
LIST_FOR_EACH_ENTRY
(
obj
,
&
thread_data
->
objects
,
jsdisp_t
,
entry
)
{
for
(
prop
=
obj
->
props
,
props_end
=
prop
+
obj
->
prop_cnt
;
prop
<
props_end
;
prop
++
)
{
switch
(
prop
->
type
)
{
case
PROP_JSVAL
:
...
...
@@ -841,7 +842,7 @@ HRESULT gc_run(script_ctx_t *ctx)
}
/* 2. Clear mark on objects with non-zero "external refcount" and all objects accessible from them */
LIST_FOR_EACH_ENTRY
(
obj
,
&
ctx
->
objects
,
jsdisp_t
,
entry
)
{
LIST_FOR_EACH_ENTRY
(
obj
,
&
thread_data
->
objects
,
jsdisp_t
,
entry
)
{
if
(
!
obj
->
ref
||
!
obj
->
gc_marked
)
continue
;
...
...
@@ -899,7 +900,7 @@ HRESULT gc_run(script_ctx_t *ctx)
/* For weak refs, traverse paths accessible from it via the WeakMaps, if the WeakMaps are alive at this point.
We need both the key and the WeakMap for the entry to actually be accessible (and thus traversed). */
if
(
obj2
->
has_weak_refs
)
{
struct
list
*
list
=
&
RB_ENTRY_VALUE
(
rb_get
(
&
ctx
->
weak_refs
,
obj2
),
struct
weak_refs_entry
,
entry
)
->
list
;
struct
list
*
list
=
&
RB_ENTRY_VALUE
(
rb_get
(
&
thread_data
->
weak_refs
,
obj2
),
struct
weak_refs_entry
,
entry
)
->
list
;
struct
weakmap_entry
*
entry
;
LIST_FOR_EACH_ENTRY
(
entry
,
list
,
struct
weakmap_entry
,
weak_refs_entry
)
{
...
...
@@ -926,7 +927,7 @@ HRESULT gc_run(script_ctx_t *ctx)
/* Restore */
chunk
=
head
;
chunk_idx
=
0
;
LIST_FOR_EACH_ENTRY
(
obj
,
&
ctx
->
objects
,
jsdisp_t
,
entry
)
{
LIST_FOR_EACH_ENTRY
(
obj
,
&
thread_data
->
objects
,
jsdisp_t
,
entry
)
{
obj
->
ref
=
chunk
->
ref
[
chunk_idx
++
];
if
(
chunk_idx
==
ARRAY_SIZE
(
chunk
->
ref
))
{
struct
chunk
*
next
=
chunk
->
next
;
...
...
@@ -940,13 +941,13 @@ HRESULT gc_run(script_ctx_t *ctx)
return
hres
;
/* 3. Remove all the links from the marked objects, since they are dangling */
ctx
->
gc_is_unlinking
=
TRUE
;
thread_data
->
gc_is_unlinking
=
TRUE
;
iter
=
list_head
(
&
ctx
->
objects
);
iter
=
list_head
(
&
thread_data
->
objects
);
while
(
iter
)
{
obj
=
LIST_ENTRY
(
iter
,
jsdisp_t
,
entry
);
if
(
!
obj
->
gc_marked
)
{
iter
=
list_next
(
&
ctx
->
objects
,
iter
);
iter
=
list_next
(
&
thread_data
->
objects
,
iter
);
continue
;
}
...
...
@@ -956,12 +957,12 @@ HRESULT gc_run(script_ctx_t *ctx)
/* Releasing unlinked object should not delete any other object,
so we can safely obtain the next pointer now */
iter
=
list_next
(
&
ctx
->
objects
,
iter
);
iter
=
list_next
(
&
thread_data
->
objects
,
iter
);
jsdisp_release
(
obj
);
}
ctx
->
gc_is_unlinking
=
FALSE
;
ctx
->
gc_last_tick
=
GetTickCount
();
thread_data
->
gc_is_unlinking
=
FALSE
;
thread_data
->
gc_last_tick
=
GetTickCount
();
return
S_OK
;
}
...
...
@@ -2174,7 +2175,7 @@ HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *b
unsigned
i
;
/* FIXME: Use better heuristics to decide when to run the GC */
if
(
GetTickCount
()
-
ctx
->
gc_last_tick
>
30000
)
if
(
GetTickCount
()
-
ctx
->
thread_data
->
gc_last_tick
>
30000
)
gc_run
(
ctx
);
TRACE
(
"%p (%p)
\n
"
,
dispex
,
prototype
);
...
...
@@ -2201,7 +2202,7 @@ HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *b
script_addref
(
ctx
);
dispex
->
ctx
=
ctx
;
list_add_tail
(
&
ctx
->
objects
,
&
dispex
->
entry
);
list_add_tail
(
&
ctx
->
thread_data
->
objects
,
&
dispex
->
entry
);
return
S_OK
;
}
...
...
@@ -2241,7 +2242,7 @@ void jsdisp_free(jsdisp_t *obj)
TRACE
(
"(%p)
\n
"
,
obj
);
if
(
obj
->
has_weak_refs
)
{
struct
list
*
list
=
&
RB_ENTRY_VALUE
(
rb_get
(
&
obj
->
ctx
->
weak_refs
,
obj
),
struct
weak_refs_entry
,
entry
)
->
list
;
struct
list
*
list
=
&
RB_ENTRY_VALUE
(
rb_get
(
&
obj
->
ctx
->
thread_data
->
weak_refs
,
obj
),
struct
weak_refs_entry
,
entry
)
->
list
;
do
{
remove_weakmap_entry
(
LIST_ENTRY
(
list
->
next
,
struct
weakmap_entry
,
weak_refs_entry
));
}
while
(
obj
->
has_weak_refs
);
...
...
dlls/jscript/jscript.c
View file @
bc45b43a
...
...
@@ -88,6 +88,7 @@ void script_release(script_ctx_t *ctx)
ctx
->
jscaller
->
ctx
=
NULL
;
IServiceProvider_Release
(
&
ctx
->
jscaller
->
IServiceProvider_iface
);
release_thread_data
(
ctx
->
thread_data
);
free
(
ctx
);
}
...
...
@@ -719,13 +720,6 @@ static ULONG WINAPI JScript_Release(IActiveScript *iface)
return
ref
;
}
static
int
weak_refs_compare
(
const
void
*
key
,
const
struct
rb_entry
*
entry
)
{
const
struct
weak_refs_entry
*
weak_refs_entry
=
RB_ENTRY_VALUE
(
entry
,
const
struct
weak_refs_entry
,
entry
);
ULONG_PTR
a
=
(
ULONG_PTR
)
key
,
b
=
(
ULONG_PTR
)
LIST_ENTRY
(
weak_refs_entry
->
list
.
next
,
struct
weakmap_entry
,
weak_refs_entry
)
->
key
;
return
(
a
>
b
)
-
(
a
<
b
);
}
static
HRESULT
WINAPI
JScript_SetScriptSite
(
IActiveScript
*
iface
,
IActiveScriptSite
*
pass
)
{
...
...
@@ -764,8 +758,6 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
ctx
->
html_mode
=
This
->
html_mode
;
ctx
->
acc
=
jsval_undefined
();
list_init
(
&
ctx
->
named_items
);
list_init
(
&
ctx
->
objects
);
rb_init
(
&
ctx
->
weak_refs
,
weak_refs_compare
);
heap_pool_init
(
&
ctx
->
tmp_heap
);
hres
=
create_jscaller
(
ctx
);
...
...
@@ -774,6 +766,8 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
return
hres
;
}
thread_data
->
ref
++
;
ctx
->
thread_data
=
thread_data
;
ctx
->
last_match
=
jsstr_empty
();
This
->
ctx
=
ctx
;
...
...
dlls/jscript/jscript.h
View file @
bc45b43a
...
...
@@ -132,6 +132,12 @@ HRESULT builtin_set_const(script_ctx_t*,jsdisp_t*,jsval_t);
struct
thread_data
{
LONG
ref
;
LONG
thread_id
;
BOOL
gc_is_unlinking
;
DWORD
gc_last_tick
;
struct
list
objects
;
struct
rb_tree
weak_refs
;
};
struct
thread_data
*
get_thread_data
(
void
);
...
...
@@ -383,10 +389,9 @@ struct _script_ctx_t {
SCRIPTSTATE
state
;
IActiveScript
*
active_script
;
struct
thread_data
*
thread_data
;
struct
_call_frame_t
*
call_ctx
;
struct
list
named_items
;
struct
list
objects
;
struct
rb_tree
weak_refs
;
IActiveScriptSite
*
site
;
IInternetHostSecurityManager
*
secmgr
;
DWORD
safeopt
;
...
...
@@ -399,9 +404,6 @@ struct _script_ctx_t {
heap_pool_t
tmp_heap
;
BOOL
gc_is_unlinking
;
DWORD
gc_last_tick
;
jsval_t
*
stack
;
unsigned
stack_top
;
jsval_t
acc
;
...
...
dlls/jscript/jscript_main.c
View file @
bc45b43a
...
...
@@ -40,6 +40,13 @@ HINSTANCE jscript_hinstance;
static
DWORD
jscript_tls
;
static
ITypeInfo
*
dispatch_typeinfo
;
static
int
weak_refs_compare
(
const
void
*
key
,
const
struct
rb_entry
*
entry
)
{
const
struct
weak_refs_entry
*
weak_refs_entry
=
RB_ENTRY_VALUE
(
entry
,
const
struct
weak_refs_entry
,
entry
);
ULONG_PTR
a
=
(
ULONG_PTR
)
key
,
b
=
(
ULONG_PTR
)
LIST_ENTRY
(
weak_refs_entry
->
list
.
next
,
struct
weakmap_entry
,
weak_refs_entry
)
->
key
;
return
(
a
>
b
)
-
(
a
<
b
);
}
struct
thread_data
*
get_thread_data
(
void
)
{
struct
thread_data
*
thread_data
=
TlsGetValue
(
jscript_tls
);
...
...
@@ -49,6 +56,8 @@ struct thread_data *get_thread_data(void)
if
(
!
thread_data
)
return
NULL
;
thread_data
->
thread_id
=
GetCurrentThreadId
();
list_init
(
&
thread_data
->
objects
);
rb_init
(
&
thread_data
->
weak_refs
,
weak_refs_compare
);
TlsSetValue
(
jscript_tls
,
thread_data
);
}
...
...
dlls/jscript/set.c
View file @
bc45b43a
...
...
@@ -658,7 +658,7 @@ void remove_weakmap_entry(struct weakmap_entry *entry)
else
{
struct
weak_refs_entry
*
weak_refs_entry
=
LIST_ENTRY
(
next
,
struct
weak_refs_entry
,
list
);
entry
->
key
->
has_weak_refs
=
FALSE
;
rb_remove
(
&
entry
->
key
->
ctx
->
weak_refs
,
&
weak_refs_entry
->
entry
);
rb_remove
(
&
entry
->
key
->
ctx
->
thread_data
->
weak_refs
,
&
weak_refs_entry
->
entry
);
free
(
weak_refs_entry
);
}
rb_remove
(
&
weakmap
->
map
,
&
entry
->
entry
);
...
...
@@ -771,14 +771,14 @@ static HRESULT WeakMap_set(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigne
}
if
(
key
->
has_weak_refs
)
weak_refs_entry
=
RB_ENTRY_VALUE
(
rb_get
(
&
ctx
->
weak_refs
,
key
),
struct
weak_refs_entry
,
entry
);
weak_refs_entry
=
RB_ENTRY_VALUE
(
rb_get
(
&
ctx
->
thread_data
->
weak_refs
,
key
),
struct
weak_refs_entry
,
entry
);
else
{
if
(
!
(
weak_refs_entry
=
malloc
(
sizeof
(
*
weak_refs_entry
))))
{
jsval_release
(
entry
->
value
);
free
(
entry
);
return
E_OUTOFMEMORY
;
}
rb_put
(
&
ctx
->
weak_refs
,
key
,
&
weak_refs_entry
->
entry
);
rb_put
(
&
ctx
->
thread_data
->
weak_refs
,
key
,
&
weak_refs_entry
->
entry
);
list_init
(
&
weak_refs_entry
->
list
);
key
->
has_weak_refs
=
TRUE
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment