Bug 125719 - CStack Branch: Need an implementation of sanitizeStack for C stack
Summary: CStack Branch: Need an implementation of sanitizeStack for C stack
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: 528+ (Nightly build)
Hardware: All All
: P2 Normal
Assignee: Michael Saboff
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-12-13 18:09 PST by Michael Saboff
Modified: 2013-12-16 22:06 PST (History)
0 users

See Also:


Attachments
Work in progress (5.69 KB, patch)
2013-12-13 18:10 PST, Michael Saboff
no flags Details | Formatted Diff | Diff
work in progress (4.58 KB, patch)
2013-12-13 18:12 PST, Michael Saboff
no flags Details | Formatted Diff | Diff
Patch (5.77 KB, patch)
2013-12-16 11:54 PST, Michael Saboff
ggaren: review-
Details | Formatted Diff | Diff
Updated patch (7.74 KB, patch)
2013-12-16 14:10 PST, Michael Saboff
no flags Details | Formatted Diff | Diff
Patch with changes suggested by Geoff (7.40 KB, patch)
2013-12-16 21:30 PST, Michael Saboff
ggaren: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Saboff 2013-12-13 18:09:03 PST
We need  an equivalent to JSStack::sanitizeStack() for running on the C stack.
Comment 1 Michael Saboff 2013-12-13 18:10:58 PST
Created attachment 219215 [details]
Work in progress

This implementation works, but only zeros on pointer size per loop iteration.  Also, this doesn't include the necessary GC changes.
Comment 2 Michael Saboff 2013-12-13 18:12:50 PST
Created attachment 219216 [details]
work in progress

Here it is with other work in progress removed.
Comment 3 Michael Saboff 2013-12-16 11:54:28 PST
Created attachment 219338 [details]
Patch
Comment 4 Geoffrey Garen 2013-12-16 12:27:33 PST
Comment on attachment 219338 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219338&action=review

This doesn't look right.

> Source/JavaScriptCore/heap/Heap.cpp:462
> +#if ENABLE(JIT)
> +        sanitizeStackForVM(m_vm);
> +#endif

It's a bad idiom to conditionalize callers to sanitizeStack. Callers don't know anything about how sanitizeStack is implemented -- they just know that they are a good place to sanitize the stack -- so callers should not be responsible for deciding which kind of sanitization should happen. Instead, any #ifdef- or platform-specific sanitize decisions should happen inside the function implementation.

As it stands, this idiom caused you to introduce a bug: CLoop builds do not sanitize the stack anymore during GC.

> Source/JavaScriptCore/llint/LowLevelInterpreter.asm:480
> +_sanitizeStackForVM:

Why does this function need to be written in assembly? It's just a loop. I think it would be better to write a shorter function that just returned sp, and to call that function from C++. Then you could write the actual loop in C++, and even use memset.

> Source/JavaScriptCore/runtime/VM.cpp:229
> +    setLastStackTop(stack.origin());

It is bad when one thing becomes two. Is this value a "stack top" or a "stack origin"?

Let's call this function setLastStackOrigin, and the data member m_lastStackOrigin, to match the existing name.

Why is it OK to set this value only when constructing the VM? Are you assuming that a given VM will only ever run on the thread on which it's constructed? That assumption is false.

> Source/JavaScriptCore/runtime/VM.h:381
> +        void setLastStackTop(void *lastStackTop) { m_lastStackTop = lastStackTop; }

Should be "void*".

> Source/JavaScriptCore/runtime/VM.h:510
> +        void *m_lastStackTop;

Should be "void*".
Comment 5 Michael Saboff 2013-12-16 13:12:56 PST
(In reply to comment #4)
> (From update of attachment 219338 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=219338&action=review
> 
> This doesn't look right.
> 
> > Source/JavaScriptCore/heap/Heap.cpp:462
> > +#if ENABLE(JIT)
> > +        sanitizeStackForVM(m_vm);
> > +#endif
> 
> It's a bad idiom to conditionalize callers to sanitizeStack. Callers don't know anything about how sanitizeStack is implemented -- they just know that they are a good place to sanitize the stack -- so callers should not be responsible for deciding which kind of sanitization should happen. Instead, any #ifdef- or platform-specific sanitize decisions should happen inside the function implementation.

It actually should be #if !ENABLE(LLINT_CLOOP).  It is only needed when we are on the C stack.  I will move the #ifdefs to the implementation and remove it here.

> As it stands, this idiom caused you to introduce a bug: CLoop builds do not sanitize the stack anymore during GC.

The CLoop sanitizeStack call using the JSStackis a few lines below in the same function in a section of code that is protected by #if ENABLE(LLINT_CLOOP).  In that case we need to call JSStack::sanitizeStack() a different function.

> > Source/JavaScriptCore/llint/LowLevelInterpreter.asm:480
> > +_sanitizeStackForVM:
> 
> Why does this function need to be written in assembly? It's just a loop. I think it would be better to write a shorter function that just returned sp, and to call that function from C++. Then you could write the actual loop in C++, and even use memset.

If sanitizeStack is written in C++ it will be using the same stack that it wants to clear.  Although we could get things working as a C++ leaf function, any calls out to memset or possible future changes would be problematic as we don't know how much stack is required.  Writing a simple leaf function in the LLInt eliminated these kinds of problems.  I already checked with Phil that a simple loop implementation was sufficient.

> > Source/JavaScriptCore/runtime/VM.cpp:229
> > +    setLastStackTop(stack.origin());
> 
> It is bad when one thing becomes two. Is this value a "stack top" or a "stack origin"?
> 
> Let's call this function setLastStackOrigin, and the data member m_lastStackOrigin, to match the existing name.

It is the last stack top.  It needs an initial value.  The logical initial value is the base of the stack which is stack.origin().
 
> Why is it OK to set this value only when constructing the VM? Are you assuming that a given VM will only ever run on the thread on which it's constructed? That assumption is false.

I'll add code to VMEntryScope() to set it and restore it similar to setStackLimit().

> > Source/JavaScriptCore/runtime/VM.h:381
> > +        void setLastStackTop(void *lastStackTop) { m_lastStackTop = lastStackTop; }
> 
> Should be "void*".

Fixed.

> > Source/JavaScriptCore/runtime/VM.h:510
> > +        void *m_lastStackTop;
> 
> Should be "void*".

Fixed.
Comment 6 Michael Saboff 2013-12-16 14:10:26 PST
Created attachment 219351 [details]
Updated patch
Comment 7 Geoffrey Garen 2013-12-16 15:46:27 PST
Comment on attachment 219351 [details]
Updated patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219351&action=review

> Source/JavaScriptCore/llint/LLIntThunks.h:52
> +    void sanitizeStackForVM(VM*) { }

Please change this function to call vm->stack().sanitizeStack(), and remove the explicit call to stack().sanitizeStack() from Heap.cpp.

> Source/JavaScriptCore/runtime/VM.cpp:229
> +    setLastStackTop(stack.origin());

Please rename lastStackTop to lastStackOrigin.
Comment 8 Geoffrey Garen 2013-12-16 16:05:37 PST
Comment on attachment 219351 [details]
Updated patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219351&action=review

>> Source/JavaScriptCore/runtime/VM.cpp:229
>> +    setLastStackTop(stack.origin());
> 
> Please rename lastStackTop to lastStackOrigin.

OK, I understand what you're saying now: we initialize to origin, but the value is not the same as origin -- our assembly code updates it as we go.
Comment 9 Geoffrey Garen 2013-12-16 16:21:22 PST
Comment on attachment 219351 [details]
Updated patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219351&action=review

> Source/JavaScriptCore/llint/LowLevelInterpreter.asm:479
> +# void sanitizeStackForVM(VM *vm)

This should be "VM*".
Comment 10 Michael Saboff 2013-12-16 21:30:37 PST
Created attachment 219394 [details]
Patch with changes suggested by Geoff

This has the "VM*" typo fix and sanitizeStackForVM() is now declared in VM.h and the C Loop version is defined in VM.cpp.
Comment 11 Geoffrey Garen 2013-12-16 21:37:32 PST
Comment on attachment 219394 [details]
Patch with changes suggested by Geoff

View in context: https://bugs.webkit.org/attachment.cgi?id=219394&action=review

r=me

> Source/JavaScriptCore/runtime/VM.cpp:737
> +void sanitizeStackForVM(VM *vm)

Should be "VM*".
Comment 12 Michael Saboff 2013-12-16 22:06:40 PST
Committed r160694: <http://trac.webkit.org/changeset/160694>