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)
...
@@ -783,6 +783,7 @@ HRESULT gc_run(script_ctx_t *ctx)
struct
chunk
*
next
;
struct
chunk
*
next
;
LONG
ref
[
1020
];
LONG
ref
[
1020
];
}
*
head
,
*
chunk
;
}
*
head
,
*
chunk
;
struct
thread_data
*
thread_data
=
ctx
->
thread_data
;
jsdisp_t
*
obj
,
*
obj2
,
*
link
,
*
link2
;
jsdisp_t
*
obj
,
*
obj2
,
*
link
,
*
link2
;
dispex_prop_t
*
prop
,
*
props_end
;
dispex_prop_t
*
prop
,
*
props_end
;
struct
gc_ctx
gc_ctx
=
{
0
};
struct
gc_ctx
gc_ctx
=
{
0
};
...
@@ -791,7 +792,7 @@ HRESULT gc_run(script_ctx_t *ctx)
...
@@ -791,7 +792,7 @@ HRESULT gc_run(script_ctx_t *ctx)
struct
list
*
iter
;
struct
list
*
iter
;
/* Prevent recursive calls from side-effects during unlinking (e.g. CollectGarbage from host object's Release) */
/* 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
;
return
S_OK
;
if
(
!
(
head
=
malloc
(
sizeof
(
*
head
))))
if
(
!
(
head
=
malloc
(
sizeof
(
*
head
))))
...
@@ -800,7 +801,7 @@ HRESULT gc_run(script_ctx_t *ctx)
...
@@ -800,7 +801,7 @@ HRESULT gc_run(script_ctx_t *ctx)
chunk
=
head
;
chunk
=
head
;
/* 1. Save actual refcounts and decrease them speculatively as-if we unlinked the objects */
/* 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_idx
==
ARRAY_SIZE
(
chunk
->
ref
))
{
if
(
!
(
chunk
->
next
=
malloc
(
sizeof
(
*
chunk
))))
{
if
(
!
(
chunk
->
next
=
malloc
(
sizeof
(
*
chunk
))))
{
do
{
do
{
...
@@ -815,7 +816,7 @@ HRESULT gc_run(script_ctx_t *ctx)
...
@@ -815,7 +816,7 @@ HRESULT gc_run(script_ctx_t *ctx)
}
}
chunk
->
ref
[
chunk_idx
++
]
=
obj
->
ref
;
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
++
)
{
for
(
prop
=
obj
->
props
,
props_end
=
prop
+
obj
->
prop_cnt
;
prop
<
props_end
;
prop
++
)
{
switch
(
prop
->
type
)
{
switch
(
prop
->
type
)
{
case
PROP_JSVAL
:
case
PROP_JSVAL
:
...
@@ -841,7 +842,7 @@ HRESULT gc_run(script_ctx_t *ctx)
...
@@ -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 */
/* 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
)
if
(
!
obj
->
ref
||
!
obj
->
gc_marked
)
continue
;
continue
;
...
@@ -899,7 +900,7 @@ HRESULT gc_run(script_ctx_t *ctx)
...
@@ -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.
/* 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). */
We need both the key and the WeakMap for the entry to actually be accessible (and thus traversed). */
if
(
obj2
->
has_weak_refs
)
{
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
;
struct
weakmap_entry
*
entry
;
LIST_FOR_EACH_ENTRY
(
entry
,
list
,
struct
weakmap_entry
,
weak_refs_entry
)
{
LIST_FOR_EACH_ENTRY
(
entry
,
list
,
struct
weakmap_entry
,
weak_refs_entry
)
{
...
@@ -926,7 +927,7 @@ HRESULT gc_run(script_ctx_t *ctx)
...
@@ -926,7 +927,7 @@ HRESULT gc_run(script_ctx_t *ctx)
/* Restore */
/* Restore */
chunk
=
head
;
chunk_idx
=
0
;
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
++
];
obj
->
ref
=
chunk
->
ref
[
chunk_idx
++
];
if
(
chunk_idx
==
ARRAY_SIZE
(
chunk
->
ref
))
{
if
(
chunk_idx
==
ARRAY_SIZE
(
chunk
->
ref
))
{
struct
chunk
*
next
=
chunk
->
next
;
struct
chunk
*
next
=
chunk
->
next
;
...
@@ -940,13 +941,13 @@ HRESULT gc_run(script_ctx_t *ctx)
...
@@ -940,13 +941,13 @@ HRESULT gc_run(script_ctx_t *ctx)
return
hres
;
return
hres
;
/* 3. Remove all the links from the marked objects, since they are dangling */
/* 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
)
{
while
(
iter
)
{
obj
=
LIST_ENTRY
(
iter
,
jsdisp_t
,
entry
);
obj
=
LIST_ENTRY
(
iter
,
jsdisp_t
,
entry
);
if
(
!
obj
->
gc_marked
)
{
if
(
!
obj
->
gc_marked
)
{
iter
=
list_next
(
&
ctx
->
objects
,
iter
);
iter
=
list_next
(
&
thread_data
->
objects
,
iter
);
continue
;
continue
;
}
}
...
@@ -956,12 +957,12 @@ HRESULT gc_run(script_ctx_t *ctx)
...
@@ -956,12 +957,12 @@ HRESULT gc_run(script_ctx_t *ctx)
/* Releasing unlinked object should not delete any other object,
/* Releasing unlinked object should not delete any other object,
so we can safely obtain the next pointer now */
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
);
jsdisp_release
(
obj
);
}
}
ctx
->
gc_is_unlinking
=
FALSE
;
thread_data
->
gc_is_unlinking
=
FALSE
;
ctx
->
gc_last_tick
=
GetTickCount
();
thread_data
->
gc_last_tick
=
GetTickCount
();
return
S_OK
;
return
S_OK
;
}
}
...
@@ -2174,7 +2175,7 @@ HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *b
...
@@ -2174,7 +2175,7 @@ HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *b
unsigned
i
;
unsigned
i
;
/* FIXME: Use better heuristics to decide when to run the GC */
/* 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
);
gc_run
(
ctx
);
TRACE
(
"%p (%p)
\n
"
,
dispex
,
prototype
);
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
...
@@ -2201,7 +2202,7 @@ HRESULT init_dispex(jsdisp_t *dispex, script_ctx_t *ctx, const builtin_info_t *b
script_addref
(
ctx
);
script_addref
(
ctx
);
dispex
->
ctx
=
ctx
;
dispex
->
ctx
=
ctx
;
list_add_tail
(
&
ctx
->
objects
,
&
dispex
->
entry
);
list_add_tail
(
&
ctx
->
thread_data
->
objects
,
&
dispex
->
entry
);
return
S_OK
;
return
S_OK
;
}
}
...
@@ -2241,7 +2242,7 @@ void jsdisp_free(jsdisp_t *obj)
...
@@ -2241,7 +2242,7 @@ void jsdisp_free(jsdisp_t *obj)
TRACE
(
"(%p)
\n
"
,
obj
);
TRACE
(
"(%p)
\n
"
,
obj
);
if
(
obj
->
has_weak_refs
)
{
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
{
do
{
remove_weakmap_entry
(
LIST_ENTRY
(
list
->
next
,
struct
weakmap_entry
,
weak_refs_entry
));
remove_weakmap_entry
(
LIST_ENTRY
(
list
->
next
,
struct
weakmap_entry
,
weak_refs_entry
));
}
while
(
obj
->
has_weak_refs
);
}
while
(
obj
->
has_weak_refs
);
...
...
dlls/jscript/jscript.c
View file @
bc45b43a
...
@@ -88,6 +88,7 @@ void script_release(script_ctx_t *ctx)
...
@@ -88,6 +88,7 @@ void script_release(script_ctx_t *ctx)
ctx
->
jscaller
->
ctx
=
NULL
;
ctx
->
jscaller
->
ctx
=
NULL
;
IServiceProvider_Release
(
&
ctx
->
jscaller
->
IServiceProvider_iface
);
IServiceProvider_Release
(
&
ctx
->
jscaller
->
IServiceProvider_iface
);
release_thread_data
(
ctx
->
thread_data
);
free
(
ctx
);
free
(
ctx
);
}
}
...
@@ -719,13 +720,6 @@ static ULONG WINAPI JScript_Release(IActiveScript *iface)
...
@@ -719,13 +720,6 @@ static ULONG WINAPI JScript_Release(IActiveScript *iface)
return
ref
;
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
,
static
HRESULT
WINAPI
JScript_SetScriptSite
(
IActiveScript
*
iface
,
IActiveScriptSite
*
pass
)
IActiveScriptSite
*
pass
)
{
{
...
@@ -764,8 +758,6 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
...
@@ -764,8 +758,6 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
ctx
->
html_mode
=
This
->
html_mode
;
ctx
->
html_mode
=
This
->
html_mode
;
ctx
->
acc
=
jsval_undefined
();
ctx
->
acc
=
jsval_undefined
();
list_init
(
&
ctx
->
named_items
);
list_init
(
&
ctx
->
named_items
);
list_init
(
&
ctx
->
objects
);
rb_init
(
&
ctx
->
weak_refs
,
weak_refs_compare
);
heap_pool_init
(
&
ctx
->
tmp_heap
);
heap_pool_init
(
&
ctx
->
tmp_heap
);
hres
=
create_jscaller
(
ctx
);
hres
=
create_jscaller
(
ctx
);
...
@@ -774,6 +766,8 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
...
@@ -774,6 +766,8 @@ static HRESULT WINAPI JScript_SetScriptSite(IActiveScript *iface,
return
hres
;
return
hres
;
}
}
thread_data
->
ref
++
;
ctx
->
thread_data
=
thread_data
;
ctx
->
last_match
=
jsstr_empty
();
ctx
->
last_match
=
jsstr_empty
();
This
->
ctx
=
ctx
;
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);
...
@@ -132,6 +132,12 @@ HRESULT builtin_set_const(script_ctx_t*,jsdisp_t*,jsval_t);
struct
thread_data
{
struct
thread_data
{
LONG
ref
;
LONG
ref
;
LONG
thread_id
;
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
);
struct
thread_data
*
get_thread_data
(
void
);
...
@@ -383,10 +389,9 @@ struct _script_ctx_t {
...
@@ -383,10 +389,9 @@ struct _script_ctx_t {
SCRIPTSTATE
state
;
SCRIPTSTATE
state
;
IActiveScript
*
active_script
;
IActiveScript
*
active_script
;
struct
thread_data
*
thread_data
;
struct
_call_frame_t
*
call_ctx
;
struct
_call_frame_t
*
call_ctx
;
struct
list
named_items
;
struct
list
named_items
;
struct
list
objects
;
struct
rb_tree
weak_refs
;
IActiveScriptSite
*
site
;
IActiveScriptSite
*
site
;
IInternetHostSecurityManager
*
secmgr
;
IInternetHostSecurityManager
*
secmgr
;
DWORD
safeopt
;
DWORD
safeopt
;
...
@@ -399,9 +404,6 @@ struct _script_ctx_t {
...
@@ -399,9 +404,6 @@ struct _script_ctx_t {
heap_pool_t
tmp_heap
;
heap_pool_t
tmp_heap
;
BOOL
gc_is_unlinking
;
DWORD
gc_last_tick
;
jsval_t
*
stack
;
jsval_t
*
stack
;
unsigned
stack_top
;
unsigned
stack_top
;
jsval_t
acc
;
jsval_t
acc
;
...
...
dlls/jscript/jscript_main.c
View file @
bc45b43a
...
@@ -40,6 +40,13 @@ HINSTANCE jscript_hinstance;
...
@@ -40,6 +40,13 @@ HINSTANCE jscript_hinstance;
static
DWORD
jscript_tls
;
static
DWORD
jscript_tls
;
static
ITypeInfo
*
dispatch_typeinfo
;
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
*
get_thread_data
(
void
)
{
{
struct
thread_data
*
thread_data
=
TlsGetValue
(
jscript_tls
);
struct
thread_data
*
thread_data
=
TlsGetValue
(
jscript_tls
);
...
@@ -49,6 +56,8 @@ struct thread_data *get_thread_data(void)
...
@@ -49,6 +56,8 @@ struct thread_data *get_thread_data(void)
if
(
!
thread_data
)
if
(
!
thread_data
)
return
NULL
;
return
NULL
;
thread_data
->
thread_id
=
GetCurrentThreadId
();
thread_data
->
thread_id
=
GetCurrentThreadId
();
list_init
(
&
thread_data
->
objects
);
rb_init
(
&
thread_data
->
weak_refs
,
weak_refs_compare
);
TlsSetValue
(
jscript_tls
,
thread_data
);
TlsSetValue
(
jscript_tls
,
thread_data
);
}
}
...
...
dlls/jscript/set.c
View file @
bc45b43a
...
@@ -658,7 +658,7 @@ void remove_weakmap_entry(struct weakmap_entry *entry)
...
@@ -658,7 +658,7 @@ void remove_weakmap_entry(struct weakmap_entry *entry)
else
{
else
{
struct
weak_refs_entry
*
weak_refs_entry
=
LIST_ENTRY
(
next
,
struct
weak_refs_entry
,
list
);
struct
weak_refs_entry
*
weak_refs_entry
=
LIST_ENTRY
(
next
,
struct
weak_refs_entry
,
list
);
entry
->
key
->
has_weak_refs
=
FALSE
;
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
);
free
(
weak_refs_entry
);
}
}
rb_remove
(
&
weakmap
->
map
,
&
entry
->
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
...
@@ -771,14 +771,14 @@ static HRESULT WeakMap_set(script_ctx_t *ctx, jsval_t vthis, WORD flags, unsigne
}
}
if
(
key
->
has_weak_refs
)
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
{
else
{
if
(
!
(
weak_refs_entry
=
malloc
(
sizeof
(
*
weak_refs_entry
))))
{
if
(
!
(
weak_refs_entry
=
malloc
(
sizeof
(
*
weak_refs_entry
))))
{
jsval_release
(
entry
->
value
);
jsval_release
(
entry
->
value
);
free
(
entry
);
free
(
entry
);
return
E_OUTOFMEMORY
;
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
);
list_init
(
&
weak_refs_entry
->
list
);
key
->
has_weak_refs
=
TRUE
;
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