Closed
Bug 418128
Opened 16 years ago
Closed 16 years ago
Yet another GC hazard with ++/-- in js_Interpret
Categories
(Core :: JavaScript Engine, defect, P2)
Core
JavaScript Engine
Tracking
()
VERIFIED
FIXED
mozilla1.9
People
(Reporter: igor, Assigned: igor)
Details
(Keywords: verified1.8.1.15, Whiteboard: [sg:critical?] trunk fixed in bug 418641)
Attachments
(3 files, 7 obsolete files)
11.44 KB,
patch
|
brendan
:
review+
dveditz
:
approval1.8.1.15+
|
Details | Diff | Splinter Review |
6.45 KB,
patch
|
Details | Diff | Splinter Review | |
10.74 KB,
patch
|
igor
:
review+
|
Details | Diff | Splinter Review |
The current implementation of ++ and -- operators in js_Interpret to increase/decrease indexed property of an object does not root the id of the property. This leads to a GC hazard when code tries to save the result back into object as the following example demonstrates: ~/m/ff/mozilla/js/src $ cat ~/m/y.js var obj = {}; var id = { toString: function() { return ""+Math.pow(2, 0.1); } } obj[id] = { valueOf: unrooter }; print(obj[id]++); gc(); print(uneval(obj)); function unrooter() { delete obj[id]; gc(); return 10; } ~/m/ff/mozilla/js/src $ ~/m/ff/mozilla/js/src/Linux_All_OPT.OBJ/js ~/m/y.js before 16384, after 16384, break 09ffc000 10 before 16384, after 16384, break 09ffc000 segmentation fault
Assignee | ||
Comment 1•16 years ago
|
||
There is another hazard in the ++/-- implementation. The code in js_Interpret that stores the result contains: ok = OBJ_SET_PROPERTY(cx, obj, id, &rval); ... PUSH_OPND(rtmp); Here for pre "++" and "--" operations rval == rtmp == incremenetd_or_decremented_value. When rval does not fit the int range, it will be a newborn double representing the result. So this code assumes that after the property setter returns, rval still will be alive GC thing that can be stored back to the stack. But this is not true in general. Consider array_length_setter from jsarray.c. It contains the following code: if (!ValueIsLength(cx, *vp, &newlen)) return JS_FALSE; if (!js_GetLengthProperty(cx, obj, &oldlen)) return JS_FALSE; if (oldlen > newlen) { if (oldlen - newlen < (1 << 24)) { do { --oldlen; if (!JS_CHECK_OPERATION_LIMIT(cx, JSOW_JUMP) || !DeleteArrayElement(cx, obj, oldlen)) { return JS_FALSE; } } while (oldlen != newlen); ... } if (!IndexToValue(cx, newlen, vp)) return JS_FALSE; STOBJ_SET_SLOT(obj, JSSLOT_ARRAY_LENGTH, *vp); Here vp is &rval. When oldlen > newlen, the code can call operational callback. That in turn can call the full GC collecting the context of vp. In such situation when the setter returns, rtemp, the original value of rval, will refer to the collected value and the code will push it back into JS stack. I.e., if the operation callback runs the GC, then the following example will store the dead value into x: var a = Array(1 << 30 + 1); var x = --a.length; Note that there is no hazard in the array code as vp is never read again after a potential GC call. It is precisely the ++/-- implementation that introduces the hazard when it accesses weakly rooted value after calling a setter.
Assignee | ||
Updated•16 years ago
|
Flags: blocking1.9?
Flags: blocking1.8.1.13?
Updated•16 years ago
|
Flags: blocking1.9? → blocking1.9+
Target Milestone: --- → mozilla1.9beta4
Assignee | ||
Comment 2•16 years ago
|
||
Untested patch. To fix the first hazard, the patch always roots the result of FETCH_ELEMT_ID. To fix the second hazard the patch makes sure preincrements also includes JOF_TMPSLOT. Besides the fix the patch also moves non-int increment and decrement to separated functions to share and simplify the code for this infrequently taken path. This shrinks the size of stripped jsinterp.o on Linux by 2K. The patch is not tested.
Assignee | ||
Comment 3•16 years ago
|
||
I filed bug 418641 as a cover bug for this.
No longer blocks: 418641
Updated•16 years ago
|
Flags: wanted1.8.1.x+
Whiteboard: [sg:critical?]
Assignee | ||
Comment 4•16 years ago
|
||
The new patch from bug 418641 comment 4 fixes this. It never passes pointers to unrooted values to getters/setters. This may seems excessive since the rest of code still passes &rval/&rtmp to the native functions. But given the history of hazards, I prefer not to rely on weak roots at all. Plus in fact &rval/&rtmp are expensive code wise since they force the compiler to assume that rval/rtmp can be modified by arbitrary native functions. On the other hand &sp is not exposed so sp lives most of the time in registers. Thus passing &rval and &sp[-1] and using rval or sp[-1] generates the same amount of code. In the former case the compiler will use native_stack_register[offset_for_rval] and in the latter case register_storing_sp[-1].
Comment 5•16 years ago
|
||
Patch is kinda big and scary... will this land on the trunk anytime soon so we can check for regressions?
Assignee | ||
Comment 6•16 years ago
|
||
(In reply to comment #5) > Patch is kinda big and scary... will this land on the trunk anytime soon so we > can check for regressions? Note that the branch would require rather different patch as there rooting id is not trivial. So I will go there for a minimal patch that uses JS_KEEP_ATOMS for rooting the id and will apply JSOF_TEMPSLOT for index and property operations. But I do plan to replace the main macro implementing ++/-- for non-integer cases by a function to follow the trunk.
Comment 7•16 years ago
|
||
Moving bugs that aren't beta 4 blockers to target final release.
Target Milestone: mozilla1.9beta4 → mozilla1.9
Updated•16 years ago
|
Flags: tracking1.9+ → blocking1.9+
Priority: -- → P2
Comment 8•16 years ago
|
||
Since the trunk patch hasn't been reviewed or landed on trunk we'll likely have to wait for next branch release to catch this one. Minusing for '13
Flags: blocking1.8.1.14?
Flags: blocking1.8.1.13?
Flags: blocking1.8.1.13-
Assignee | ||
Comment 9•16 years ago
|
||
This is fixed on the trunk since landing bug 418641.
Status: NEW → RESOLVED
Closed: 16 years ago
Resolution: --- → FIXED
Comment 10•16 years ago
|
||
Updated•16 years ago
|
Flags: in-testsuite+
Flags: in-litmus-
Comment 12•16 years ago
|
||
(In reply to comment #9) > This is fixed on the trunk since landing bug 418641. Does that mean the patch in this bug is obsolete and we should look at bug 418641 for the 1.8 branch, or that this patch was checked in when that one was?
Whiteboard: [sg:critical?] → [sg:critical?] fixed by bug 418641 ?
Assignee | ||
Comment 13•16 years ago
|
||
(In reply to comment #12) > (In reply to comment #9) > > This is fixed on the trunk since landing bug 418641. > > Does that mean the patch in this bug is obsolete and we should look at bug > 418641 for the 1.8 branch, or that this patch was checked in when that one was? The branch requires a new separated patch. The patch in this bug or in the bug 418641 can serve only as a guideline.
Assignee | ||
Updated•16 years ago
|
Attachment #304256 -
Attachment is obsolete: true
Updated•16 years ago
|
Flags: blocking1.8.1.15? → blocking1.8.1.15+
Whiteboard: [sg:critical?] fixed by bug 418641 ? → [sg:critical?] fixed in bug 418641
Assignee | ||
Comment 14•16 years ago
|
||
This is what I am going to test on 2008-06-04 late evening PST. Still I am asking for an early review to make sure that I have not missed anything in the patch. To solve the problem with unrooted id the patch uses JS_KEEP_ATOMS. For the problem of the setter unrooting the pre-increment result the patch makes sure that an extra temporary slot is allocated both for post- and pre-increment.
Attachment #323761 -
Flags: review?(brendan)
Comment 15•16 years ago
|
||
Comment on attachment 323761 [details] [diff] [review] fix for 1.8 branch Looks good. Assuming it all tests well too. r=me. /be
Attachment #323761 -
Flags: review?(brendan)
Attachment #323761 -
Flags: review+
Attachment #323761 -
Flags: approval1.8.1.15?
Comment 16•16 years ago
|
||
Comment on attachment 323761 [details] [diff] [review] fix for 1.8 branch Approved for 1.8.1.15, a=dveditz for release-drivers
Attachment #323761 -
Flags: approval1.8.1.15? → approval1.8.1.15+
Assignee | ||
Comment 17•16 years ago
|
||
Comment on attachment 323761 [details] [diff] [review] fix for 1.8 branch The patch regressed the js shell test suite.
Attachment #323761 -
Attachment is obsolete: true
Attachment #323761 -
Flags: approval1.8.1.15+
Assignee | ||
Comment 18•16 years ago
|
||
Now the patch passes shell tests without regressions: in the previous one I "optimized" ++/-- for var and args too much. To Bob Clary: is there a slow test list for 1.8.1 branch? When I run the tests on sm-valgrind01 with -L slow-n.js it takes 3 hours or so.
Attachment #312529 -
Attachment is obsolete: true
Attachment #324028 -
Flags: review?(brendan)
Assignee | ||
Comment 19•16 years ago
|
||
The previous attachment has a wrong patch
Attachment #324028 -
Attachment is obsolete: true
Attachment #324029 -
Flags: review?(brendan)
Attachment #324028 -
Flags: review?(brendan)
Assignee | ||
Updated•16 years ago
|
Attachment #324029 -
Attachment is patch: true
Attachment #324029 -
Attachment mime type: application/octet-stream → text/plain
Comment 20•16 years ago
|
||
(In reply to comment #18) > > To Bob Clary: is there a slow test list for 1.8.1 branch? When I run the tests > on sm-valgrind01 with -L slow-n.js it takes 3 hours or so. No, but I can create branch specific versions. Are you using jsDriver with the default timeout? It is rather long at 3600 seconds. -T 480 or -T 120 will cut it down to more manageable period.
Updated•16 years ago
|
Whiteboard: [sg:critical?] fixed in bug 418641 → [sg:critical?] need branch r=brendan; trunk fixed in bug 418641
Comment 21•16 years ago
|
||
Comment on attachment 324029 [details] [diff] [review] fix for 1.8 branch v2 for real Sorry I missed that! /be
Attachment #324029 -
Flags: review?(brendan)
Attachment #324029 -
Flags: review+
Attachment #324029 -
Flags: approval1.8.1.15?
Updated•16 years ago
|
Whiteboard: [sg:critical?] need branch r=brendan; trunk fixed in bug 418641 → [sg:critical?] trunk fixed in bug 418641
Comment 22•16 years ago
|
||
Comment on attachment 324029 [details] [diff] [review] fix for 1.8 branch v2 for real Approved for 1.8.1.15, a=dveditz for release-drivers
Attachment #324029 -
Flags: approval1.8.1.15? → approval1.8.1.15+
Assignee | ||
Comment 23•16 years ago
|
||
I checked in the patch from the comment 19 to the MOZILLA_1_8_BRANCH: Checking in jsemit.c; /cvsroot/mozilla/js/src/jsemit.c,v <-- jsemit.c new revision: 3.128.2.77; previous revision: 3.128.2.76 done Checking in jsinterp.c; /cvsroot/mozilla/js/src/jsinterp.c,v <-- jsinterp.c new revision: 3.181.2.101; previous revision: 3.181.2.100 done
Keywords: fixed1.8.1.15
Comment 24•16 years ago
|
||
verified fixed 1.8.1.15 linux/mac/win
Keywords: fixed1.8.1.15 → verified1.8.1.15
Comment 25•16 years ago
|
||
Comment 26•16 years ago
|
||
Comment on attachment 325247 [details] [diff] [review] 1.8.0 attempt the other option would have been to pull in bug 352272 - however, thats 1.7 from what i can tell; thus this backport. Anyway, it fixes the crash for me too.
Attachment #325247 -
Flags: review?(igor)
Comment 27•16 years ago
|
||
Comment 28•16 years ago
|
||
Without patch: js> before 7157, after 6409, break 0070e000 Segmentation fault
Flags: blocking1.8.0.15+
Comment 29•16 years ago
|
||
Comment on attachment 325247 [details] [diff] [review] 1.8.0 attempt we found a glitch, will attach updated one
Attachment #325247 -
Flags: review?(igor) → review-
Comment 30•16 years ago
|
||
2nd attempt
Attachment #325247 -
Attachment is obsolete: true
Attachment #325248 -
Attachment is obsolete: true
Attachment #325249 -
Flags: review?(igor)
Comment 31•16 years ago
|
||
Assignee | ||
Comment 32•16 years ago
|
||
Comment on attachment 325249 [details] [diff] [review] 1.8.0 attempt 2 >Index: jsemit.c > if (pn2->pn_type != TOK_NAME && >- (js_CodeSpec[op].format & JOF_POST) && >+ (js_CodeSpec[op].format & (JOF_INC | JOF_DEC)) && > (uintN)++cg->stackDepth > cg->maxStackDepth) { > cg->maxStackDepth = cg->stackDepth; ... > >- if (pn2->pn_type != TOK_NAME && (js_CodeSpec[op].format & JOF_POST)) >+ if (pn2->pn_type != TOK_NAME && (js_CodeSpec[op].format & (JOF_INC | JOF_DEC))) > --cg->stackDepth; Right, on 1.8 there was only one place to patch as there the first "if" affected only cg->maxStackDepth without touching cg->stackDepth. On 1.8.0 both places has to be patched. >Index: jsinterp.c > /* The operand must contain a number. */ >+ /* Preload for use in the if/else immediately below. */ >+ cs = &js_CodeSpec[op]; >+ On 1.8.0 branch cs is always initialized before interpreter's switch. There is no need to assign it again and these 3 added lines can be removed. r+ with this fixed.
Attachment #325249 -
Flags: review?(igor)
Comment 33•16 years ago
|
||
Attachment #325249 -
Attachment is obsolete: true
Assignee | ||
Updated•16 years ago
|
Attachment #325262 -
Flags: review+
Updated•16 years ago
|
Group: security
Comment 34•16 years ago
|
||
/cvsroot/mozilla/js/tests/js1_5/GC/regress-418128.js,v <-- regress-418128.js initial revision: 1.1 changeset: 15651:33dac11fb9ed
You need to log in
before you can comment on or make changes to this bug.
Description
•