Closed
Bug 935855
Opened 12 years ago
Closed 12 years ago
Investigate having the jit read JSObject* directly out of C++ objects sometimes
Categories
(Core :: DOM: Core & HTML, defect)
Tracking
()
RESOLVED
FIXED
mozilla28
People
(Reporter: bzbarsky, Assigned: bzbarsky)
References
(Blocks 1 open bug)
Details
(Keywords: dev-doc-complete, Whiteboard: [qa-])
Attachments
(7 files, 6 obsolete files)
|
5.63 KB,
patch
|
peterv
:
review+
|
Details | Diff | Splinter Review |
|
4.73 KB,
patch
|
peterv
:
review+
|
Details | Diff | Splinter Review |
|
10.12 KB,
patch
|
peterv
:
review+
efaust
:
review+
|
Details | Diff | Splinter Review |
|
13.88 KB,
patch
|
peterv
:
review+
|
Details | Diff | Splinter Review |
|
11.94 KB,
patch
|
efaust
:
review+
|
Details | Diff | Splinter Review |
|
40.45 KB,
patch
|
Details | Diff | Splinter Review | |
|
4.29 KB,
patch
|
jorendorff
:
review+
|
Details | Diff | Splinter Review |
We may want this for window's "document" member, as well as ImageData.data.
I wrote up a version of this that just calls ExposeObjectToActiveJS and another version that inlines the barrier/nursery bits but keeps calls for the GCThingIsMarkedGray/UnmarkGrayGCThingRecursively stuff, and a third version that inlines all of it except the UnmarkGrayGCThingRecursively bits (though this version is not quite correct; see below).
Times, if I'm measuring this correctly, on my hardware:
Normal DOM getter for ImageData.data: 8ns
JIT fast path, calls ExposeObjectToActiveJS: 4.5ns
With the barriering inlined: 4.2ns
With GCThingIsMarkedGray inlined: 2.6ns
With all the barrier/etc logic removed: 0.7ns
The one caveat is that inlining GCThingIsMarkedGray requires doing this in jitcode:
uintptr_t(1) << (bit % nbits)
and I see no way to do that in our macro assembler (I can shift a register by a 32-bit immediate, but I can't shift by the value stored in a register). Am I just missing something?
Also, all variants of the JIT fast path assume the object's wrapper and the stored JSObject* are in the same compartment. There is no attempt to enforce this. That's certainly part of the speedup.
Finally, I have no particular confidence that my barriering jitcode is correct.... certainly it doesn't quite match what ExposeGCThingToActiveJS does, in that we still check for gray bits even if the barrier stuff triggered. We'd have to have a way for patchableCallPreBarrier to not bind &done and instead return it to avoid that.
In any case, the main question is whether this is worth doing and if so which of the stages above we want to do...
Flags: needinfo?(jdemooij)
| Assignee | ||
Comment 1•12 years ago
|
||
We want this no matter what, since it lets us avoid Xray gunk for ImageData.data
Attachment #828495 -
Flags: review?(peterv)
| Assignee | ||
Updated•12 years ago
|
Assignee: nobody → bzbarsky
Status: NEW → ASSIGNED
| Assignee | ||
Comment 2•12 years ago
|
||
Attachment #828496 -
Flags: review?(peterv)
Attachment #828496 -
Flags: review?(efaustbmo)
| Assignee | ||
Comment 3•12 years ago
|
||
This is with ExposeObjectToActiveJS called via callWithABI
| Assignee | ||
Comment 4•12 years ago
|
||
| Assignee | ||
Comment 5•12 years ago
|
||
| Assignee | ||
Comment 6•12 years ago
|
||
Missed some hackery that should be removed....
| Assignee | ||
Updated•12 years ago
|
Attachment #828497 -
Attachment is obsolete: true
Comment 7•12 years ago
|
||
(In reply to Boris Zbarsky [:bz] from comment #0)
> The one caveat is that inlining GCThingIsMarkedGray requires doing this in
> jitcode:
>
> uintptr_t(1) << (bit % nbits)
>
> and I see no way to do that in our macro assembler (I can shift a register
> by a 32-bit immediate, but I can't shift by the value stored in a register).
> Am I just missing something?
It's an x86 quirk: you can shift by the value stored in a register, but that register MUST be ecx. We could add something to the macro-assembler though, and assert on x86/x64 that the rhs register == ecx. Then we can ask the register allocator to reserve ecx as temp, or push/pop ecx before using it...
How many instructions do you have to emit to inline this? We could also generate a small shared code stub that we store in JitRuntime and can just call for every member access.
> In any case, the main question is whether this is worth doing and if so
> which of the stages above we want to do...
Does it noticeably improve non-micro benchmarks? I think you're in the best position to decide if it's worth it; you know where we can use it and what the implementation will look like.
Just calling ExposeObjectToActiveJS seems to make us almost 2x faster, maybe that's a good first step?
Flags: needinfo?(jdemooij)
Comment 8•12 years ago
|
||
Looking at the code, it doesn't seem too bad though: lots of bit twiddling but it's fairly straight-forward and I don't expect this to change often.
It would still be nice to move the inlined ExposeObjectToActiveJS code to its own IonCode stub though so that we can just call that for every LGetDOMMember instruction. It's an extra call + ret instruction, but it avoids code bloat. Then if the call to UnmarkGrayGCThingRecursively is really cold, we can stop marking LGetDOMMember as call instruction and just do the spilling/restoring ourselves before/after the callWithABI.
| Assignee | ||
Comment 9•12 years ago
|
||
> How many instructions do you have to emit to inline this?
For the fully inlined version, JIT Inspector says:
[GetDOMMember]
movq 0x20(%rcx), %rax
shlq $1, %rax
movq 0x18(%rax), %rax
jmp ((1967))
push %rdx
leaq 0x18(%rax), %rdx
call ((1977))
pop %rdx
jmp ((1983))
.balign 8, 0xf4 # hlt
##link ((1983)) jumps to ((1984))
##link ((1967)) jumps to ((1984))
movq %rax, %rsi
movq $-1048576, %rdx
andq %rdx, %rsi
movl $0xfc0b0, %edx
orq %rdx, %rsi
movq %rax, %rdx
movl $0xfffff, %ecx
andq %rcx, %rdx
shrq $3, %rdx
addq $0x1, %rdx
movq %rdx, %rcx
shrq $6, %rdx
andq $0x3f, %rcx
movq 0(%rsi,%rdx,8), %rsi
movl $0x1, %edx
andq %rsi, %rdx
testq %rdx, %rdx
je ((2056))
push %rax
movq %rax, %rdi
xorl %esi, %esi
movq %rsp, %rdx
andq $0xfffffff0, %rsp
push %rdx
subq $0x8, %rsp
movabsq $0x1013e3690, %rax
call *%rax
addq $0x8, %rsp
pop %rsp
pop %rax
##link ((2056)) jumps to ((2092))
(but that's still missing the 1 << (bit % nbits) stuff, whatever that will end up looking like).
For comparison, the minimal version that just does a callWithABI to ExposeObjectToActiveJS looks like this:
[GetDOMMember]
movq 0x20(%rdx), %rdi
shlq $1, %rdi
movq 0x18(%rdi), %rdi
push %rdi
movq %rsp, %rsi
andq $0xfffffff0, %rsp
push %rsi
subq $0x8, %rsp
movabsq $0x1016001d0, %rax
call *%rax
addq $0x8, %rsp
pop %rsp
pop %rax
> It would still be nice to move the inlined ExposeObjectToActiveJS code to its own IonCode
> stub
I suspect that you're right here. I just don't know how to do it yet. Happy to have someone pick that part up. ;)
> Then if the call to UnmarkGrayGCThingRecursively is really cold
It should be, as far as I know, yes.
| Assignee | ||
Comment 10•12 years ago
|
||
> Does it noticeably improve non-micro benchmarks?
The main motivation for me finally doing this was bug 935283. Right now, "document" is an own value property on Window; changing it to a getter definitely significantly slowed down things (several % regressions on jQuery performance). But that getter currently takes about 30ns. Presumably we'd get that down to 10 or so once we convert Window to WebIDL. But that's still slower than the 0.7 we have right now. So the real question is how we avoid performance regressions when we go back to having document be an accessor property, and this bug was one possible answer, with the goal being to approximate the current slot read as closely as possible, on the assumption that then we definitely won't regress stuff. I just started with ImageData.data because it's the one other place I know offhand where we want this and performance matters and I could test it easily.
Olli, Bill, are there things we could do that would allow us to skip the barrier and or check-for-gray bits? For example, is there something the C++ end could do to ensure that the member ("document", say) is never gray when the actual object (window, say) is black, at which point we could presumably skip all the gray checking in the jitcode here?
Flags: needinfo?(wmccloskey)
Flags: needinfo?(bugs)
Comment 11•12 years ago
|
||
(In reply to Boris Zbarsky [:bz] from comment #9)
> > How many instructions do you have to emit to inline this?
>
> For the fully inlined version, JIT Inspector says:
>
> [GetDOMMember]
> ...
> movq $-1048576, %rdx
> andq %rdx, %rsi
This should be andq $-1048576, %rsi.
> movl $0xfc0b0, %edx
> orq %rdx, %rsi
This should be orq $0xfc0b0, %rsi.
> movq %rax, %rdx
> movl $0xfffff, %ecx
> andq %rcx, %rdx
This should be andq $0xffffff, %rdx.
> shrq $3, %rdx
> addq $0x1, %rdx
> movq %rdx, %rcx
> shrq $6, %rdx
> andq $0x3f, %rcx
> movq 0(%rsi,%rdx,8), %rsi
> movl $0x1, %edx
> andq %rsi, %rdx
> testq %rdx, %rdx
> je ((2056))
We ought to be emitting:
testq $0x1, %rsi
je LABEL
for this (assuming %rdx isn't being used in the path at LABEL).
Is there an easy way to tell which bits of the JIT are producing these parts of the code? (Point still stands about this being too slow, of course.)
Flags: needinfo?(bzbarsky)
(In reply to Boris Zbarsky [:bz] from comment #10)
> Olli, Bill, are there things we could do that would allow us to skip the
> barrier and or check-for-gray bits? For example, is there something the C++
> end could do to ensure that the member ("document", say) is never gray when
> the actual object (window, say) is black, at which point we could presumably
> skip all the gray checking in the jitcode here?
Olli or Andrew know much more about this than I do. It sounds like something we ought to be able to do, though, if we're not doing it already. I think it would be an improvement to the cycle collector as well (fewer gray objects to scan).
If that doesn't pan out, I have another idea for the gray bits. Most mark bits are not gray. At the end of a GC, we might be able to set a special flag in every arena that has something gray in it. This would have good cache locality, so it would probably be quite fast. I expect that most arenas would end up not having this flag set. So we could check that flag in the fast path, rather than the actual mark bit. If the flag is true, we would take an out-of-line path that would do what we do now.
| Assignee | ||
Comment 13•12 years ago
|
||
> This should be andq $-1048576, %rsi.
There is no such thing on x86-64, afaict. Keep in mind that the constant there is a 64-bit one in this case (it looks negative, but it's actually just very large), but immediates can only be 32-bit.
> This should be orq $0xfc0b0, %rsi.
This one could be if I added some static asserts about the value fitting in 32 bits, yes. Good catch. I was being too conservative because of the issue above.
> This should be andq $0xffffff, %rdx.
Yes, with some asserts about it fitting in 32 bits.
> We ought to be emitting:
Don't forget that there's a missing left-shift of edx by rcx there because I have no way to emit it right now.
> Is there an easy way to tell which bits of the JIT are producing these parts of the
> code?
It's all explicitly in the patch; this is all the manual bitslinging the patch is doing. For example, this bit:
> movq $-1048576, %rdx
> andq %rdx, %rsi
is this part of the patch:
+ // addr &= ~js::gc::ChunkMask. Make sure to not truncate the
+ // immediate to 32 bits!
+ masm.movePtr(ImmWord(~js::gc::ChunkMask), scratch);
+ masm.andPtr(scratch, arg2Reg);
Flags: needinfo?(bzbarsky)
| Assignee | ||
Comment 14•12 years ago
|
||
Andrew, see comment 10 and comment 12?
I agree that if we can just end up with a fast common path putting all the complexity off on a out of line call that should work wonderfully.
Flags: needinfo?(continuation)
Comment 15•12 years ago
|
||
(In reply to Boris Zbarsky [:bz] from comment #13)
> > This should be andq $-1048576, %rsi.
>
> There is no such thing on x86-64, afaict. Keep in mind that the constant
> there is a 64-bit one in this case (it looks negative, but it's actually
> just very large), but immediates can only be 32-bit.
and accepts sign-extended 32-bit immediates (int32_t); I think this one qualifies.
> It's all explicitly in the patch; this is all the manual bitslinging the
> patch is doing.
My mistake, I read the bugmail too quickly and didn't bother to look at the wider context of the bug.
Comment 16•12 years ago
|
||
Well during black bit propagation we do unmark gray, but that is rather manual and happens rarely.
Here we need something where when the wrapper for window is unmarked, also the wrapper for document
is unmarked.
Can we have some hidden property on window wrapper which points to document wrapper so that unmarking knows to go through it too when it deals with the wrapper for window?
Flags: needinfo?(bugs)
Comment 17•12 years ago
|
||
> For example, is there something the C++ end could do to ensure that the member ("document", say) is never gray when the actual object (window, say) is black
I don't really understand what the situation you are describing is. The "actual object" here is the reflector for the nsGlobalWindow, and the "member" is the reflector for the mDoc of the window? If the window reflector has a pointer to the document's reflector, then you already have this invariant: black-gray edges are verboten.
I guess that isn't the case though? From the GC's perspective, maybe whatever other thing owns the window's reflector, and then separately, the document's reflector is gray-rooted by the DOM, and the knowledge that the window's reflector indirectly owns the document's reflector is only in C++. Maybe the tracer for the window reflector could say that it has the document reflector as a child and then everything will just magically work? I'm not sure how weird that will get.
Comment 18•12 years ago
|
||
"magically work" meaning we will have the invariant that a black window reflector implies a black document reflector, so if JS is operating on the window reflector it can retrieve the document reflector without unmarkgray. I'm not sure if that helps with GGC stuff, but I think the idea there was already to operate under the assumption that document and window reflectors will be allocated tenured (?!?) so you might be able to avoid some of that goop too.
Flags: needinfo?(continuation)
| Assignee | ||
Comment 19•12 years ago
|
||
> I guess that isn't the case though?
Right. The thing with the pointer to mDoc's reflector would be the nsGlobalWindow.
We could give the window reflector a trace hook that traces the document reflector in the nsGlobalWindow, yes.
As for ggc, I agree that if we limit this to document we could skip it all, but I'd still like to see if I can make it work for imagedata. Of course we could add more stuff to jitinfo to indicate whether we're guaranteed tenured, I guess...
| Assignee | ||
Comment 20•12 years ago
|
||
> and accepts sign-extended 32-bit immediates (int32_t); I think this one qualifies.
Hmm. So we have a 64-bit constant that doesn't fit in 32 bits but which happens to look like a signed integer that _does_ fit in 32 bits (that is, it's very big; if it were smaller then this property would not hold). I guess we can add some static asserts to that effect and carefully cast to int64_t before passing to the int32_t argument and ignore the undefined behavior issues...
Comment 21•12 years ago
|
||
Comment on attachment 828496 [details] [diff] [review]
part 2. Store isMember information in jitinfo.
Review of attachment 828496 [details] [diff] [review]:
-----------------------------------------------------------------
Codegen changes to jitinfo look good. r=me.
::: dom/bindings/Codegen.py
@@ +6022,5 @@
> " %s, /* isInfallible. False in setters. */\n"
> " %s, /* isConstant. Only relevant for getters. */\n"
> " %s, /* isPure. Only relevant for getters. */\n"
> + " %s, /* isMember. Only relevant for getters. */\n"
> + " %s, /* Offset of the member, if isMember. */\n"
nit: Can we add some "0 otherwise" here? I realize we have a space constraint, but it would be good to note. "else 0", maybe?
Attachment #828496 -
Flags: review?(efaustbmo) → review+
Flags: needinfo?(wmccloskey)
Updated•12 years ago
|
Attachment #828495 -
Flags: review?(peterv) → review+
Comment 22•12 years ago
|
||
Comment on attachment 828496 [details] [diff] [review]
part 2. Store isMember information in jitinfo.
Review of attachment 828496 [details] [diff] [review]:
-----------------------------------------------------------------
::: content/canvas/src/ImageData.h
@@ +61,5 @@
> JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> scope);
>
> + static const size_t DataOffset()
> + {
> + return offsetof(ImageData, mData);
Or we could just hardcode this in codegen as |offsetof(nativeType, "m" + nativeMemberName)|.
Attachment #828496 -
Flags: review?(peterv) → review+
| Assignee | ||
Comment 23•12 years ago
|
||
> Or we could just hardcode this in codegen as |offsetof(nativeType, "m"
Doesn't this require the member of the nativeType to be public?
| Assignee | ||
Comment 24•12 years ago
|
||
So I was thinking. The other possible option here to get around issues like grayness and worries about compartments is to just store the value in a reserved slot and read it from there instead of from a member of the C++ object. Basically Olli's "invisible property" suggestion.
We could maybe even autogenerate code to stash it in there, to make wrapping such objects not insane.
The drawbacks are that we have to store it boxed (which is no worse than a normal JS property) and that we have to have free reserved slots to do this (which is not the case for Window right now, though maybe we can easily add one?).
Thoughts? It seems a bit less flexible than what I have here so far, but also seems like it would generate vastly better jitcode.
Comment 25•12 years ago
|
||
If we could do that in generated code, I definitely favor that.
The less we add JS* stuff to manually written C++, the better.
| Assignee | ||
Comment 26•12 years ago
|
||
I'm pretty sure we could. Just have the generated wrapping code call the normal getter when it's done and store the result in the reserved slot.
If we think we'll be able to get at least one more reserved slot on Window, I'm happy to try that out.
Flags: needinfo?(jorendorff)
Comment 27•12 years ago
|
||
Yeah, that'd be nicer. A little sad that we'd store two copies of the same value.
| Assignee | ||
Comment 28•12 years ago
|
||
Actually, there is one more complication to the reserved slot approach. When the value changes the C++ code has to reset the reserved slot. We could codegen helpers for that too, though, I think.
| Assignee | ||
Comment 29•12 years ago
|
||
Also, I'm going to not allow this on non-leaf interfaces for now, just for simplicity. That won't affect any of our use cases.
In the future, it might be nice if proxies could have "reserved C++ slots". These would be slots that would hold untagged pointers to JSObjects (and maybe other GC thing types, based on some sort of type descriptor in the proxy). Both C++ code and JS code could access them quickly. The GC would trace them as it now traces reserved slots. This would have to wait until proxies have their own classes, probably. Does it sound useful?
| Assignee | ||
Comment 31•12 years ago
|
||
Well, ideally proxies and normal objects would not differ in this regard.
For my purposes here, right now there are no proxies I need this stuff for, so I'm not blocked on the proxy situation.
Comment 32•12 years ago
|
||
(In reply to Boris Zbarsky [:bz] from comment #26)
> If we think we'll be able to get at least one more reserved slot on Window,
> I'm happy to try that out.
The customer is always right.
It should be as simple as bumping GlobalObject::APPLICATION_SLOTS in js/src/vm/GlobalObject.h. The magic of constants.
Flags: needinfo?(jorendorff)
| Assignee | ||
Comment 33•12 years ago
|
||
Ah, awesome. ;)
So I have a prototype of this, and it's nice and fast. Just cleaning it up now.
| Assignee | ||
Comment 34•12 years ago
|
||
Attachment #830992 -
Flags: review?(peterv)
| Assignee | ||
Updated•12 years ago
|
Attachment #828495 -
Attachment is obsolete: true
| Assignee | ||
Comment 35•12 years ago
|
||
Attachment #830996 -
Flags: review?(peterv)
| Assignee | ||
Comment 36•12 years ago
|
||
Attachment #830997 -
Flags: review?(peterv)
Attachment #830997 -
Flags: review?(efaustbmo)
| Assignee | ||
Comment 37•12 years ago
|
||
Attachment #831011 -
Flags: review?(peterv)
| Assignee | ||
Comment 38•12 years ago
|
||
Attachment #831012 -
Flags: review?(efaustbmo)
| Assignee | ||
Updated•12 years ago
|
Attachment #828501 -
Attachment is obsolete: true
| Assignee | ||
Updated•12 years ago
|
Attachment #828496 -
Attachment is obsolete: true
| Assignee | ||
Updated•12 years ago
|
Attachment #828499 -
Attachment is obsolete: true
| Assignee | ||
Updated•12 years ago
|
Attachment #828500 -
Attachment is obsolete: true
Comment 39•12 years ago
|
||
Comment on attachment 831012 [details] [diff] [review]
part 5. Use our members-in-slots information in ion codegen.
Review of attachment 831012 [details] [diff] [review]:
-----------------------------------------------------------------
::: js/src/jit/CodeGenerator.cpp
@@ +7320,5 @@
>
> bool
> +CodeGenerator::visitGetDOMMember(LGetDOMMember *ins)
> +{
> + // It's simple to duplicate visitLoadFixedSlotV here than it is to try to
simpler?
::: js/src/jit/IonBuilder.cpp
@@ +8374,5 @@
> + // We can't use MLoadFixedSlot here because it might not have the
> + // right aliasing behavior; we want to alias DOM setters.
> + get = MGetDOMMember::New(jitinfo, obj, guard);
> + } else
> + get = MGetDOMProperty::New(jitinfo, obj, guard);
{}
| Assignee | ||
Comment 40•12 years ago
|
||
> simpler?
Yes, thank you.
> {}
Afaik, not in jseng.
Comment 41•12 years ago
|
||
(In reply to Boris Zbarsky [:bz] from comment #40)
> Afaik, not in jseng.
No, it should be braced: "However, if either the consequent or alternate is a block of multiple statements, braces are used on both." (from https://wiki.mozilla.org/JavaScript:SpiderMonkey:C_Coding_Style )
Comment 42•12 years ago
|
||
Though I guess IonMonkey has its own style which I am unfamiliar with...
Comment 43•12 years ago
|
||
(In reply to Andrew McCreight [:mccr8] from comment #42)
> Though I guess IonMonkey has its own style which I am unfamiliar with...
Same applies to IonMonkey code.
(AFAIK IonMonkey style == SpiderMonkey style, except "//" comments and maybe different naming for class/struct members, but not sure whether the SM style guide says anything about that. Both of these also start to show up in non-Ion code though.)
| Assignee | ||
Comment 44•12 years ago
|
||
Comment 45•12 years ago
|
||
Comment on attachment 830997 [details] [diff] [review]
part 2. Store isSlot information in jitinfo.
Review of attachment 830997 [details] [diff] [review]:
-----------------------------------------------------------------
Looks good to me, after reading the rollup patch. r=me
::: dom/bindings/Codegen.py
@@ +192,5 @@
> return ""
> def define(self):
> traceHook = TRACE_HOOK_NAME if self.descriptor.customTrace else 'nullptr'
> callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr'
> + slotCount = INSTANCE_RESERVED_SLOTS
I see that this line changes in part 3. It must do so, else the scheme makes no sense.
Attachment #830997 -
Flags: review?(efaustbmo) → review+
Comment 46•12 years ago
|
||
Comment on attachment 831012 [details] [diff] [review]
part 5. Use our members-in-slots information in ion codegen.
Review of attachment 831012 [details] [diff] [review]:
-----------------------------------------------------------------
Very nicely done. This system is a pain to navigate. I'm also really happy to see that the gray object unmarking stuff went away because we didn't need it. \o/. r=me with single nit addresed.
::: js/src/jit/CodeGenerator.cpp
@@ +7324,5 @@
> + // It's simple to duplicate visitLoadFixedSlotV here than it is to try to
> + // use an LLoadFixedSlotV or some subclass of it for this case: that would
> + // require us to have MGetDOMMember inherit from MLoadFixedSlot, and then
> + // we'd have to duplicate a bunch of stuff we now get for free from
> + // MGetDOMProperty.
That's fine. GetDOMMember is much more the logical child of GetDOMProperty and LoadFixedSlotV, though they do similar work. masm.loadValue is a fine place to leave the abtraction.
::: js/src/jit/IonBuilder.cpp
@@ +8374,5 @@
> + // We can't use MLoadFixedSlot here because it might not have the
> + // right aliasing behavior; we want to alias DOM setters.
> + get = MGetDOMMember::New(jitinfo, obj, guard);
> + } else
> + get = MGetDOMProperty::New(jitinfo, obj, guard);
nit: Ms2ger is right. The braces in js/ should match in both arms, regardless of the length of either one.
Attachment #831012 -
Flags: review?(efaustbmo) → review+
| Assignee | ||
Comment 47•12 years ago
|
||
> nit: Ms2ger is right.
The world is ending. ;)
I'll add the braces. Thanks for the review!
Updated•12 years ago
|
Attachment #830992 -
Flags: review?(peterv) → review+
Updated•12 years ago
|
Attachment #830997 -
Flags: review?(peterv) → review+
Comment 48•12 years ago
|
||
Comment on attachment 830996 [details] [diff] [review]
part 3. Compute the right slot indices to use for members we want to store in slots and save then in the data model the WebIDL parser outputs.
Review of attachment 830996 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/bindings/Codegen.py
@@ +6046,5 @@
> getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
> isInSlot = self.member.getExtendedAttribute("StoreInSlot")
> if isInSlot:
> slotIndex = INSTANCE_RESERVED_SLOTS + self.member.slotIndex;
> + if slotIndex >= 16 : # JS engine currently allows 16 fixed slots
FIXED_SLOTS_MAX seems to be 31? It'd be nice to assert this in the C++ somewhere.
Attachment #830996 -
Flags: review?(peterv) → review+
Comment 49•12 years ago
|
||
Comment on attachment 831011 [details] [diff] [review]
part 4. Codegen a function that updates all the members-in-reserved-slots values for an interface and call it when we finish wrapping an object.
Review of attachment 831011 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/bindings/Codegen.py
@@ +8361,5 @@
> cgThings.append(CGConstructorEnabledViaFunc(descriptor))
>
> if descriptor.concrete:
> if descriptor.proxy:
> + if descriptor.interface.totalMembersInSlots != 0 and False:
Er, I think you should drop |and False|.
Attachment #831011 -
Flags: review?(peterv) → review+
| Assignee | ||
Comment 50•12 years ago
|
||
> FIXED_SLOTS_MAX seems to be 31?
Hmm. bhackett had told me 16. And that there was no sane way to assert this stuff.
Jason, is there a way DOM code can statically assert how many fixed slots we can have?
> Er, I think you should drop |and False|.
Er, yes. I was testing something and forgot to revert that part. Good catch!
| Assignee | ||
Comment 51•12 years ago
|
||
Let's try actually needinfoing Jason for the bit in comment 50.
Flags: needinfo?(jorendorff)
| Assignee | ||
Comment 52•12 years ago
|
||
Talked to Jason on IRC. We'll add a friend API constant for max reserved slots.
Flags: needinfo?(jorendorff)
| Assignee | ||
Comment 53•12 years ago
|
||
Attachment #8337890 -
Flags: review?(jorendorff)
Comment 54•12 years ago
|
||
Comment on attachment 8337890 [details] [diff] [review]
part 6. Add friend API exposing the max number of fixed slots, and some static asserts that we're not going past it.
Review of attachment 8337890 [details] [diff] [review]:
-----------------------------------------------------------------
You wrote:
<bz> jorendorff: Shape::FIXED_SLOTS_MAX is the biggest count of fixed slots a Shape can store
<bz> jorendorff: JSObject::MAX_FIXED_SLOTS is the biggest number of fixed slots our GC size classes will give an object
Please put those in as one-line comments on the definitions of these constants in vm/Shape.h and jsobj.h respectively.
::: dom/bindings/Codegen.py
@@ +2479,5 @@
> "}\n"
> "js::SetReservedSlot(aWrapper, %d, args.rval());" %
> + (m.slotIndex + INSTANCE_RESERVED_SLOTS,
> + self.descriptor.interface.identifier.name, m.identifier.name,
> + m.identifier.name, m.slotIndex + INSTANCE_RESERVED_SLOTS))
Micro-nit: I would common up the index computation and give it a local variable.
::: js/src/jsfriendapi.h
@@ +408,5 @@
> return fixedSlots()[slot];
> return slots[slot - nfixed];
> }
> +
> + static const uint32_t MAX_FIXED_SLOTS = 16;
Comment the actual contract here: reserved slots with index <= this number are guaranteed to be fixed. (Right?)
::: js/src/vm/Shape.h
@@ +1312,5 @@
> JS_STATIC_ASSERT(offsetof(Shape, slotInfo) == offsetof(js::shadow::Shape, slotInfo));
> JS_STATIC_ASSERT(FIXED_SLOTS_SHIFT == js::shadow::Shape::FIXED_SLOTS_SHIFT);
> + static_assert(js::shadow::Object::MAX_FIXED_SLOTS <= FIXED_SLOTS_MAX,
> + "Our public maximum number of fixed slots should fit "
> + "in our fixed slot count storage");
Comment golf! I love this game. My best:
"verify numFixedSlots() bitfield is big enough"
Yours is fine, but the word "public" is a red herring.
Attachment #8337890 -
Flags: review?(jorendorff) → review+
| Assignee | ||
Comment 55•12 years ago
|
||
> Micro-nit: I would common up the index computation and give it a local variable.
Pain inside array comprehensions. I went with:
def slotIndex(member):
return member.slotIndex + INSTANCE_RESERVED_SLOTS
outside the comprehension and slotIndex(m) inside the comprehension.
Fixed up the rest, though it's reserved slots with index < MAX_FIXED_SLOTS, not <=. Thank you for the review (and the excellent comment suggestions).
| Assignee | ||
Comment 56•12 years ago
|
||
Per irc discussion, I tweaked part 1 to disallow StoreInSlot on attributes with a throwing getter, since that combination makes no sense.
https://hg.mozilla.org/integration/mozilla-inbound/rev/70ad99f6a10a
https://hg.mozilla.org/integration/mozilla-inbound/rev/733f98e1f5d0
https://hg.mozilla.org/integration/mozilla-inbound/rev/aefcfaae2534
https://hg.mozilla.org/integration/mozilla-inbound/rev/96db6fab0b50
https://hg.mozilla.org/integration/mozilla-inbound/rev/717a05a70859
https://hg.mozilla.org/integration/mozilla-inbound/rev/b4592ec867ad
Flags: in-testsuite?
Target Milestone: --- → mozilla28
Comment 57•12 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/70ad99f6a10a
https://hg.mozilla.org/mozilla-central/rev/733f98e1f5d0
https://hg.mozilla.org/mozilla-central/rev/aefcfaae2534
https://hg.mozilla.org/mozilla-central/rev/96db6fab0b50
https://hg.mozilla.org/mozilla-central/rev/717a05a70859
https://hg.mozilla.org/mozilla-central/rev/b4592ec867ad
Status: ASSIGNED → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
| Assignee | ||
Comment 58•12 years ago
|
||
Keywords: dev-doc-complete
Updated•12 years ago
|
Whiteboard: [qa-]
Updated•7 years ago
|
Component: DOM → DOM: Core & HTML
You need to log in
before you can comment on or make changes to this bug.
Description
•