Reviewers: antonm,
Message:
Anton,
This is a quick fix I needed while debugging window.open memory leak
reported by
Pavel (I don't know the bug number). In short, repeatedly opening/closing
gmail
window using window.open/close leaks memory. I don't think the result cache
is
the only thing to blame here, but fixing it helps with heap tracing. I'm
sure
there're better ways to fix it.
I'm also working on adding debug-mode checks for this.
Thanks,
Vitaly
Description:
Don't share function result caches between contexts.
A reference to the caches array was embedded directly into the builtin
code and this allowed sharing objects between contexts.
Unfortunately, clearing the cache on GC won't prevent sharing so we
either have to have per-context builtin code or load the cache
indirectly from the current context. This change implements the second
approach. The first approach may be interesting to consider in the
future for some perfomance critical functions, and the current
approach can still be improved by putting the caches directly into the
global context (or even global objects).
Please review this at http://codereview.chromium.org/1731002/show
Affected files:
M src/arm/codegen-arm.cc
M src/ia32/codegen-ia32.cc
M src/x64/codegen-x64.cc
Index: src/arm/codegen-arm.cc
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index
b2fe05f5a3acaffc3742669cd025865cdc42c897..909b6b944285bd6fe7752a48e22c35f5b214cf87
100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -4172,18 +4172,21 @@ void
CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) {
frame_->EmitPush(r0);
return;
}
- Handle<FixedArray> cache_obj(
- FixedArray::cast(jsfunction_result_caches->get(cache_id)));
Load(args->at(1));
frame_->EmitPop(r2);
+ __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ __ ldr(r1, FieldMemOperand(r1, GlobalObject::kGlobalContextOffset));
+ __ ldr(r1, MemOperand(r1, Context::SlotOffset(
+ Context::JSFUNCTION_RESULT_CACHES_INDEX)));
+ __ ldr(r1, FieldMemOperand(r1, FixedArray::OffsetOfElementAt(cache_id)));
+
DeferredSearchCache* deferred = new DeferredSearchCache(r0, r1, r2);
const int kFingerOffset =
FixedArray::OffsetOfElementAt(JSFunctionResultCache::kFingerIndex);
ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
- __ mov(r1, Operand(cache_obj));
__ ldr(r0, FieldMemOperand(r1, kFingerOffset));
// r0 now holds finger offset as a smi.
__ add(r3, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
Index: src/ia32/codegen-ia32.cc
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index
5ab7a531f325679e5285d045aadaa570625b56e4..340cd674f599485cfa4f2e92edf0f9026cfbf995
100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -6551,17 +6551,24 @@ void
CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) {
frame_->Push(Factory::undefined_value());
return;
}
- Handle<FixedArray> cache_obj(
- FixedArray::cast(jsfunction_result_caches->get(cache_id)));
Load(args->at(1));
Result key = frame_->Pop();
key.ToRegister();
Result cache = allocator()->Allocate();
- __ mov(cache.reg(), cache_obj);
+ ASSERT(cache.is_valid());
+ __ mov(cache.reg(), Operand(esi,
Context::SlotOffset(Context::GLOBAL_INDEX)));
+ __ mov(cache.reg(),
+ FieldOperand(cache.reg(), GlobalObject::kGlobalContextOffset));
+ __ mov(cache.reg(),
+ Operand(cache.reg(),
+
Context::SlotOffset(Context::JSFUNCTION_RESULT_CACHES_INDEX)));
+ __ mov(cache.reg(),
+ FieldOperand(cache.reg(),
FixedArray::OffsetOfElementAt(cache_id)));
Result tmp = allocator()->Allocate();
+ ASSERT(tmp.is_valid());
DeferredSearchCache* deferred = new DeferredSearchCache(tmp.reg(),
cache.reg(),
Index: src/x64/codegen-x64.cc
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index
a6aa36d731f200074ada2760b67cf349235763f8..21ac7ba36c01c876da1e7f6a69c22ef4e379e607
100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -4297,17 +4297,26 @@ void
CodeGenerator::GenerateGetFromCache(ZoneList<Expression*>* args) {
frame_->Push(Factory::undefined_value());
return;
}
- Handle<FixedArray> cache_obj(
- FixedArray::cast(jsfunction_result_caches->get(cache_id)));
Load(args->at(1));
Result key = frame_->Pop();
key.ToRegister();
Result cache = allocator()->Allocate();
- __ movq(cache.reg(), cache_obj, RelocInfo::EMBEDDED_OBJECT);
+ ASSERT(cache.is_valid());
+ __ movq(cache.reg(),
+ Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ __ movq(cache.reg(),
+ FieldOperand(cache.reg(), GlobalObject::kGlobalContextOffset));
+ __ movq(cache.reg(),
+ Operand(cache.reg(),
+ Context::SlotOffset(
+ Context::JSFUNCTION_RESULT_CACHES_INDEX)));
+ __ movq(cache.reg(),
+ FieldOperand(cache.reg(),
FixedArray::OffsetOfElementAt(cache_id)));
Result tmp = allocator()->Allocate();
+ ASSERT(tmp.is_valid());
DeferredSearchCache* deferred = new DeferredSearchCache(tmp.reg(),
cache.reg(),
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev