Closed Bug 1166041 Opened 10 years ago Closed 10 years ago

Intermittent LeakSanitizer | leak at js_pod_malloc, pod_malloc, js::Nursery::allocateBuffer, AllocateObjectBuffer or js_pod_malloc, AllocateObjectBuffer, js::NativeObject::growSlots, js::NativeObject::updateSlotsForSpan

Categories

(Core :: JavaScript: GC, defect)

x86_64
Linux
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla43
Tracking Status
firefox40 --- unaffected
firefox41 --- fixed
firefox42 --- fixed
firefox43 --- fixed
firefox-esr38 --- unaffected

People

(Reporter: RyanVM, Assigned: jandem)

References

(Blocks 1 open bug)

Details

(Keywords: intermittent-failure, memory-leak)

Attachments

(3 files, 1 obsolete file)

11:36:35 INFO - ==1906==ERROR: LeakSanitizer: detected memory leaks 11:36:35 INFO - Direct leak of 64 byte(s) in 1 object(s) allocated from: 11:36:35 INFO - #0 0x472111 in malloc /builds/slave/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74 11:36:35 INFO - #1 0x7f8b25e85a7e in js_malloc /builds/slave/fx-team-l64-asan-0000000000000/build/src/obj-firefox/js/src/../../dist/include/js/Utility.h:119 11:36:35 INFO - #2 0x7f8b25e85a7e in js_pod_malloc<unsigned char> /builds/slave/fx-team-l64-asan-0000000000000/build/src/obj-firefox/js/src/../../dist/include/js/Utility.h:274 11:36:35 INFO - #3 0x7f8b25e85a7e in pod_malloc<unsigned char> /builds/slave/fx-team-l64-asan-0000000000000/build/src/js/src/vm/MallocProvider.h:63 11:36:35 INFO - #4 0x7f8b25e85a7e in js::Nursery::allocateBuffer(JSObject*, unsigned int) /builds/slave/fx-team-l64-asan-0000000000000/build/src/js/src/gc/Nursery.cpp:263 11:36:35 INFO - #5 0x7f8b25fe750d in AllocateObjectBuffer<js::HeapSlot> /builds/slave/fx-team-l64-asan-0000000000000/build/src/js/src/gc/Nursery-inl.h:55 11:36:35 INFO - #6 0x7f8b25fe750d in js::NativeObject::growSlots(js::ExclusiveContext*, unsigned int, unsigned int) /builds/slave/fx-team-l64-asan-0000000000000/build/src/js/src/vm/NativeObject.cpp:399 11:36:36 INFO - #7 0x7f8b25fe6581 in js::NativeObject::updateSlotsForSpan(js::ExclusiveContext*, unsigned long, unsigned long) /builds/slave/fx-team-l64-asan-0000000000000/build/src/js/src/vm/NativeObject.cpp:262 11:36:36 INFO - #8 0x7f8b25fe61ca in js::NativeObject::setLastProperty(js::ExclusiveContext*, js::Shape*) /builds/slave/fx-team-l64-asan-0000000000000/build/src/js/src/vm/NativeObject.cpp:298:10
Blocks: LSan
Ping?
Flags: needinfo?(terrence)
Appears to be new with Brian's rewrite of this subsystem.
Flags: needinfo?(terrence) → needinfo?(bhackett1024)
At least I think it starts around the time that that landed. Brian, feel free to punt this back my way if you disagree.
Attached patch bug1166041-nursery-leak — — Splinter Review
We actually intentionally leak slots memory on that path if we hit OOM inserting into a hash table. Here's a patch to tighten that up and fail the allocation instead.
Attachment #8612271 - Flags: review?(terrence)
Comment on attachment 8612271 [details] [diff] [review] bug1166041-nursery-leak Review of attachment 8612271 [details] [diff] [review]: ----------------------------------------------------------------- Yup, better to just raise the error.
Attachment #8612271 - Flags: review?(terrence) → review+
Assignee: nobody → jcoppeard
Status: NEW → ASSIGNED
Flags: needinfo?(bhackett1024)
(In reply to Treeherder Robot from comment #113) This was on a rev after your push :(
Flags: needinfo?(jcoppeard)
Keywords: leave-open
(In reply to Ryan VanderMeulen [:RyanVM UTC-4] from comment #114) Oh well it was worth fixing that first. The real cause must be something more subtle.
Attached patch bug1166041-leak-asserts — — Splinter Review
Add some assertions to hopefully catch this.
Flags: needinfo?(jcoppeard)
Attachment #8620893 - Flags: review?(terrence)
Attachment #8620893 - Flags: review?(terrence) → review+
Andrew, is it possible to increase the number of lines of backtrace we get for these failures? We don't have enough here to see beyond NativeObject::setLastProperty() which is still pretty generic.
Flags: needinfo?(continuation)
The current value was set by decoder to reduce memory usage. This is determined by the ASan option malloc_context_size[1]. I'm not sure how common this leak is, but you could try increasing it a bit and then doing a try run with a bunch of retriggers. I'm not sure how badly it would fall over, or if we use AWS machines with the same amount of RAM now or what. [1] http://mxr.mozilla.org/mozilla-central/search?string=malloc_context_size&filter=[Mm]alloc_context_size
Flags: needinfo?(continuation)
(In reply to Andrew McCreight [:mccr8] from comment #305) > The current value was set by decoder to reduce memory usage. Actually that was me, bug 977921 has some info. However that was before Mochitest-bc was split up and it was more than a year ago, so it's probably fine to increase that value now and see if anything breaks.
I captured some more backtrace but it still doesn't tell us much: 05:03:31 INFO - Direct leak of 64 byte(s) in 1 object(s) allocated from: 05:03:31 INFO - #0 0x472231 in malloc /builds/slave/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74 05:03:31 INFO - #1 0x7f1ad0bfeb5e in js_malloc /builds/slave/try-l64-asan-00000000000000000/build/src/obj-firefox/js/src/../../dist/include/js/Utility.h:135 05:03:31 INFO - #2 0x7f1ad0bfeb5e in js_pod_malloc<unsigned char> /builds/slave/try-l64-asan-00000000000000000/build/src/obj-firefox/js/src/../../dist/include/js/Utility.h:290 05:03:31 INFO - #3 0x7f1ad0bfeb5e in pod_malloc<unsigned char> /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/MallocProvider.h:63 05:03:31 INFO - #4 0x7f1ad0bfeb5e in js::Nursery::allocateBuffer(JSObject*, unsigned int) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/gc/Nursery.cpp:264 05:03:31 INFO - #5 0x7f1ad0d8b81c in AllocateObjectBuffer<js::HeapSlot> /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/gc/Nursery-inl.h:60 05:03:31 INFO - #6 0x7f1ad0d8b81c in js::NativeObject::growSlots(js::ExclusiveContext*, unsigned int, unsigned int) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:402 05:03:31 INFO - #7 0x7f1ad0d8a72b in js::NativeObject::updateSlotsForSpan(js::ExclusiveContext*, unsigned long, unsigned long) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:262 05:03:31 INFO - #8 0x7f1ad0d8a2ed in js::NativeObject::setLastProperty(js::ExclusiveContext*, js::Shape*) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:298:10 05:03:31 INFO - #9 0x7f1ad0e236aa in js::NativeObject::getChildProperty(js::ExclusiveContext*, JS::Handle<js::NativeObject*>, JS::Handle<js::Shape*>, js::StackShape&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Shape.cpp:414 05:03:31 INFO - #10 0x7f1ad0e01831 in js::NativeObject::addPropertyInternal(js::ExclusiveContext*, JS::Handle<js::NativeObject*>, JS::Handle<jsid>, bool (*)(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>), bool (*)(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>, JS::ObjectOpResult&), unsigned int, unsigned int, unsigned int, js::ShapeTable::Entry*, bool) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Shape.cpp:581 05:03:31 INFO - #11 0x7f1ad0df9bb7 in js::NativeObject::putProperty(js::ExclusiveContext*, JS::Handle<js::NativeObject*>, JS::Handle<jsid>, bool (*)(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>), bool (*)(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>, JS::ObjectOpResult&), unsigned int, unsigned int, unsigned int) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Shape.cpp:728 05:03:31 INFO - #12 0x7f1ad0d96d1f in AddOrChangeProperty(js::ExclusiveContext*, JS::Handle<js::NativeObject*>, JS::Handle<jsid>, JS::Handle<JSPropertyDescriptor>) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:1151 05:03:31 INFO - #13 0x7f1ad0d94b6f in js::NativeDefineProperty(js::ExclusiveContext*, JS::Handle<js::NativeObject*>, JS::Handle<jsid>, JS::Handle<JSPropertyDescriptor>, JS::ObjectOpResult&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:1366
Summary: Intermittent LeakSanitizer | leak at js_pod_malloc, pod_malloc, js::Nursery::allocateBuffer, AllocateObjectBuffer → Intermittent LeakSanitizer | leak at js_pod_malloc, pod_malloc, js::Nursery::allocateBuffer, AllocateObjectBuffer or js_pod_malloc, AllocateObjectBuffer, js::NativeObject::growSlots, js::NativeObject::updateSlotsForSpan
Captured more context. It might be a cross compartment wrapper whose slots we are leaking. 03:39:40 INFO - ==2132==ERROR: LeakSanitizer: detected memory leaks 03:39:40 INFO - Direct leak of 64 byte(s) in 1 object(s) allocated from: 03:39:40 INFO - #0 0x472271 in malloc /builds/slave/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:74 03:39:40 INFO - #1 0x7fbdeaf66278 in js_malloc /builds/slave/try-l64-asan-00000000000000000/build/src/obj-firefox/js/src/../../dist/include/js/Utility.h:135 03:39:40 INFO - #2 0x7fbdeaf66278 in js_pod_malloc<unsigned char> /builds/slave/try-l64-asan-00000000000000000/build/src/obj-firefox/js/src/../../dist/include/js/Utility.h:290 03:39:40 INFO - #3 0x7fbdeaf66278 in unsigned char* js::MallocProvider<JS::Zone>::pod_malloc<unsigned char>(unsigned long) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/MallocProvider.h:63 03:39:40 INFO - #4 0x7fbdeaebbdcc in AllocateObjectBuffer<js::HeapSlot> /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/gc/Nursery-inl.h:60 03:39:40 INFO - #5 0x7fbdeaebbdcc in js::NativeObject::growSlots(js::ExclusiveContext*, unsigned int, unsigned int) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:402 03:39:40 INFO - #6 0x7fbdeaebacdb in js::NativeObject::updateSlotsForSpan(js::ExclusiveContext*, unsigned long, unsigned long) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:262 03:39:40 INFO - #7 0x7fbdeaeba89d in js::NativeObject::setLastProperty(js::ExclusiveContext*, js::Shape*) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:298:10 03:39:40 INFO - #8 0x7fbdeaf53daa in js::NativeObject::getChildProperty(js::ExclusiveContext*, JS::Handle<js::NativeObject*>, JS::Handle<js::Shape*>, js::StackShape&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Shape.cpp:414 03:39:40 INFO - #9 0x7fbdeaf31f51 in js::NativeObject::addPropertyInternal(js::ExclusiveContext*, JS::Handle<js::NativeObject*>, JS::Handle<jsid>, bool (*)(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>), bool (*)(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>, JS::ObjectOpResult&), unsigned int, unsigned int, unsigned int, js::ShapeTable::Entry*, bool) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Shape.cpp:581 03:39:40 INFO - #10 0x7fbdeaf2a2d7 in js::NativeObject::putProperty(js::ExclusiveContext*, JS::Handle<js::NativeObject*>, JS::Handle<jsid>, bool (*)(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>), bool (*)(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>, JS::ObjectOpResult&), unsigned int, unsigned int, unsigned int) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Shape.cpp:728 03:39:40 INFO - #11 0x7fbdeaec72cf in AddOrChangeProperty(js::ExclusiveContext*, JS::Handle<js::NativeObject*>, JS::Handle<jsid>, JS::Handle<JSPropertyDescriptor>) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:1151 03:39:40 INFO - #12 0x7fbdeaec511c in js::NativeDefineProperty(js::ExclusiveContext*, JS::Handle<js::NativeObject*>, JS::Handle<jsid>, JS::Handle<JSPropertyDescriptor>, JS::ObjectOpResult&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:1366 03:39:40 INFO - #13 0x7fbdeb9a3401 in js::DefineProperty(js::ExclusiveContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::Handle<JS::Value>, bool (*)(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>), bool (*)(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::MutableHandle<JS::Value>, JS::ObjectOpResult&), unsigned int, JS::ObjectOpResult&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/jsobj.cpp:2626 03:39:40 INFO - #14 0x7fbdeaed2f5c in js::SetPropertyByDefining(JSContext*, JS::Handle<JSObject*>, JS::Handle<jsid>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, bool, JS::ObjectOpResult&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:2119 03:39:40 INFO - #15 0x7fbdeaed7574 in SetNonexistentProperty(JSContext*, JS::Handle<js::NativeObject*>, JS::Handle<jsid>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::QualifiedBool, JS::ObjectOpResult&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:2180 03:39:40 INFO - #16 0x7fbdeaed5eb8 in js::NativeSetProperty(JSContext*, JS::Handle<js::NativeObject*>, JS::Handle<jsid>, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::QualifiedBool, JS::ObjectOpResult&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.cpp:2353 03:39:40 INFO - #17 0x7fbdeadea43b in SetProperty /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/NativeObject.h:1434 03:39:40 INFO - #18 0x7fbdeadea43b in SetPropertyOperation /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:317 03:39:40 INFO - #19 0x7fbdeadea43b in Interpret(JSContext*, js::RunState&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:2777 03:39:40 INFO - #20 0x7fbdeadd7914 in js::RunScript(JSContext*, js::RunState&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:661 03:39:40 INFO - #21 0x7fbdeadb8c90 in js::Invoke(JSContext*, JS::CallArgs, js::MaybeConstruct) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:738 03:39:40 INFO - #22 0x7fbdeae08d8d in js::InvokeConstructor(JSContext*, JS::CallArgs) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:805 03:39:40 INFO - #23 0x7fbdeae09641 in js::InvokeConstructor(JSContext*, JS::Value, unsigned int, JS::Value const*, bool, JS::MutableHandle<JS::Value>) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:835 03:39:40 INFO - #24 0x7fbdeba9cd3b in construct /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/proxy/DirectProxyHandler.cpp:85 03:39:40 INFO - #25 0x7fbdeba9cd3b in js::CrossCompartmentWrapper::construct(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) const /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/proxy/CrossCompartmentWrapper.cpp:309 03:39:40 INFO - #26 0x7fbdebaadf70 in js::Proxy::construct(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/proxy/Proxy.cpp:410 03:39:40 INFO - #27 0x7fbdebab09c2 in js::proxy_Construct(JSContext*, unsigned int, JS::Value*) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/proxy/Proxy.cpp:706 03:39:40 INFO - #28 0x7fbdeae08c9e in CallJSNative /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/jscntxtinlines.h:235 03:39:40 INFO - #29 0x7fbdeae08c9e in CallJSNativeConstructor /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/jscntxtinlines.h:268 03:39:40 INFO - #30 0x7fbdeae08c9e in js::InvokeConstructor(JSContext*, JS::CallArgs) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:816 03:39:40 INFO - #31 0x7fbdeadf7519 in Interpret(JSContext*, js::RunState&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:2969 03:39:40 INFO - #32 0x7fbdeadd7914 in js::RunScript(JSContext*, js::RunState&) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:661 03:39:40 INFO - #33 0x7fbdeadb8c90 in js::Invoke(JSContext*, JS::CallArgs, js::MaybeConstruct) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:738 03:39:40 INFO - #34 0x7fbdeb9172f1 in js::CallOrConstructBoundFunction(JSContext*, unsigned int, JS::Value*) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/jsfun.cpp:1545 03:39:40 INFO - #35 0x7fbdeadb84c3 in CallJSNative /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/jscntxtinlines.h:235 03:39:40 INFO - #36 0x7fbdeadb84c3 in js::Invoke(JSContext*, JS::CallArgs, js::MaybeConstruct) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:720 03:39:40 INFO - #37 0x7fbdead5bcf3 in js::Invoke(JSContext*, JS::Value const&, JS::Value const&, unsigned int, JS::Value const*, JS::MutableHandle<JS::Value>) /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/vm/Interpreter.cpp:775 03:39:40 INFO - #38 0x7fbdeba9bf7b in call /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/proxy/DirectProxyHandler.cpp:77 03:39:40 INFO - #39 0x7fbdeba9bf7b in js::CrossCompartmentWrapper::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) const /builds/slave/try-l64-asan-00000000000000000/build/src/js/src/proxy/CrossCompartmentWrapper.cpp:289
Unassigning as I'm not actively working on this.
Assignee: jcoppeard → nobody
Status: ASSIGNED → NEW
Terrence, any other ideas? This happens too frequently to just ignore. We either need a fix or suppression here if that's deemed too difficult.
Flags: needinfo?(terrence)
I'll take a look.
Attached patch wait_on_nursery_free_end-v0.diff (obsolete) — — Splinter Review
We fire off the nursery's background mallocBuffer freeing thread at the start of the shutdown GC. It looks like we only wait for it when we (1) do the next nursery sweep, (2) OOM, or (3) AutoFinishGC. I don't think we do any of these before shutting down, so we might just be killing this thread before it finishes its work.
Assignee: nobody → terrence
Status: NEW → ASSIGNED
Flags: needinfo?(terrence)
Attachment #8640101 - Flags: review?(jcoppeard)
me: Hey me, I don't need to bother giving this trivial 1 line patch even the most basic modicum of testing, do I? me: Of course not! what could go wrong? Turns out runtime init can fail, in which case the task will be nullptr. Whoops.
Attachment #8640101 - Attachment is obsolete: true
Attachment #8640101 - Flags: review?(jcoppeard)
Attachment #8640111 - Flags: review?(jcoppeard)
Comment on attachment 8640111 [details] [diff] [review] wait_on_nursery_free_end-v1.diff Review of attachment 8640111 [details] [diff] [review]: ----------------------------------------------------------------- Ah, good find.
Attachment #8640111 - Flags: review?(jcoppeard) → review+
Status: ASSIGNED → RESOLVED
Closed: 10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla42
(In reply to Treeherder Robot from comment #598) (In reply to Treeherder Robot from comment #599) (In reply to Treeherder Robot from comment #600) On the m-c merge no less :(
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
Target Milestone: mozilla42 → ---
Flags: needinfo?(terrence)
Depends on: 1194627
Looks like the fix in bug 1194627 is holding up!
Assignee: terrence → jdemooij
Status: REOPENED → RESOLVED
Closed: 10 years ago10 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla43
No instances on the release branches since bug 1194627 got uplifted.
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: