"src/compiler/zone-pool.h",
"src/compiler.cc",
"src/compiler.h",
+ "src/context-measure.cc",
+ "src/context-measure.h",
"src/contexts.cc",
"src/contexts.h",
"src/conversions-inl.h",
void SetErrorMessageForCodeGenerationFromStrings(Local<String> message);
/**
+ * Estimate the memory in bytes retained by this context.
+ */
+ size_t EstimatedSize();
+
+ /**
* Stack-allocated class which sets the execution context for all
* operations executed within a local scope.
*/
#include "src/bootstrapper.h"
#include "src/code-stubs.h"
#include "src/compiler.h"
+#include "src/context-measure.h"
#include "src/contexts.h"
#include "src/conversions-inl.h"
#include "src/counters.h"
}
+size_t Context::EstimatedSize() {
+ return static_cast<size_t>(
+ i::ContextMeasure(*Utils::OpenHandle(this)).Size());
+}
+
+
MaybeLocal<v8::Object> ObjectTemplate::NewInstance(Local<Context> context) {
PREPARE_FOR_EXECUTION(context, "v8::ObjectTemplate::NewInstance()", Object);
auto self = Utils::OpenHandle(this);
--- /dev/null
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/context-measure.h"
+
+namespace v8 {
+namespace internal {
+
+ContextMeasure::ContextMeasure(Context* context)
+ : context_(context),
+ root_index_map_(context->GetIsolate()),
+ recursion_depth_(0),
+ count_(0),
+ size_(0) {
+ DCHECK(context_->IsNativeContext());
+ Object* next_link = context_->get(Context::NEXT_CONTEXT_LINK);
+ MeasureObject(context_);
+ MeasureDeferredObjects();
+ context_->set(Context::NEXT_CONTEXT_LINK, next_link);
+}
+
+
+bool ContextMeasure::IsShared(HeapObject* object) {
+ if (object->IsScript()) return true;
+ if (object->IsSharedFunctionInfo()) return true;
+ if (object->IsScopeInfo()) return true;
+ if (object->IsCode() && !Code::cast(object)->is_optimized_code()) return true;
+ if (object->IsExecutableAccessorInfo()) return true;
+ if (object->IsWeakCell()) return true;
+ return false;
+}
+
+
+void ContextMeasure::MeasureObject(HeapObject* object) {
+ if (back_reference_map_.Lookup(object).is_valid()) return;
+ if (root_index_map_.Lookup(object) != RootIndexMap::kInvalidRootIndex) return;
+ if (IsShared(object)) return;
+ back_reference_map_.Add(object, BackReference::DummyReference());
+ recursion_depth_++;
+ if (recursion_depth_ > kMaxRecursion) {
+ deferred_objects_.Add(object);
+ } else {
+ MeasureAndRecurse(object);
+ }
+ recursion_depth_--;
+}
+
+
+void ContextMeasure::MeasureDeferredObjects() {
+ while (deferred_objects_.length() > 0) {
+ MeasureAndRecurse(deferred_objects_.RemoveLast());
+ }
+}
+
+
+void ContextMeasure::MeasureAndRecurse(HeapObject* object) {
+ int size = object->Size();
+ count_++;
+ size_ += size;
+ Map* map = object->map();
+ MeasureObject(map);
+ object->IterateBody(map->instance_type(), size, this);
+}
+
+
+void ContextMeasure::VisitPointers(Object** start, Object** end) {
+ for (Object** current = start; current < end; current++) {
+ if ((*current)->IsSmi()) continue;
+ MeasureObject(HeapObject::cast(*current));
+ }
+}
+}
+} // namespace v8::internal
--- /dev/null
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_CONTEXT_MEASURE_H_
+#define V8_CONTEXT_MEASURE_H_
+
+#include "src/snapshot/serialize.h"
+
+namespace v8 {
+namespace internal {
+
+class ContextMeasure : public ObjectVisitor {
+ public:
+ explicit ContextMeasure(Context* context);
+
+ int Size() { return size_; }
+ int Count() { return count_; }
+
+ void VisitPointers(Object** start, Object** end);
+
+ private:
+ void MeasureObject(HeapObject* object);
+ void MeasureDeferredObjects();
+ void MeasureAndRecurse(HeapObject* object);
+ bool IsShared(HeapObject* object);
+
+ Context* context_;
+
+ BackReferenceMap back_reference_map_;
+ RootIndexMap root_index_map_;
+
+ static const int kMaxRecursion = 16;
+ int recursion_depth_;
+ List<HeapObject*> deferred_objects_;
+
+ int count_;
+ int size_;
+
+ DisallowHeapAllocation no_gc_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContextMeasure);
+};
+}
+} // namespace v8::internal
+
+#endif // V8_CONTEXT_MEASURE_H_
#define V8_SNAPSHOT_SERIALIZE_H_
#include "src/hashmap.h"
-#include "src/heap-profiler.h"
#include "src/isolate.h"
#include "src/snapshot/snapshot-source-sink.h"
ChunkOffsetBits::encode(index));
}
+ static BackReference DummyReference() { return BackReference(kDummyValue); }
+
static BackReference Reference(AllocationSpace space, uint32_t chunk_index,
uint32_t chunk_offset) {
DCHECK(IsAligned(chunk_offset, kObjectAlignment));
static const uint32_t kInvalidValue = 0xFFFFFFFF;
static const uint32_t kSourceValue = 0xFFFFFFFE;
static const uint32_t kGlobalProxyValue = 0xFFFFFFFD;
+ static const uint32_t kDummyValue = 0xFFFFFFFC;
static const int kChunkOffsetSize = kPageSizeBits - kObjectAlignmentBits;
static const int kChunkIndexSize = 32 - kChunkOffsetSize - kSpaceTagSize;
"Atomics.futexWait(i32a, 0, 0);");
CHECK(try_catch.HasTerminated());
}
+
+
+TEST(EstimatedContextSize) {
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ LocalContext env;
+ CHECK(50000 < env->EstimatedSize());
+}
#include "src/v8.h"
#include "src/compilation-cache.h"
+#include "src/context-measure.h"
#include "src/deoptimizer.h"
#include "src/execution.h"
#include "src/factory.h"
FixedArrayBase::kLengthOffset));
delete buffer;
}
+
+
+TEST(ContextMeasure) {
+ CcTest::InitializeVM();
+ v8::HandleScope scope(CcTest::isolate());
+ Isolate* isolate = CcTest::i_isolate();
+ LocalContext context;
+
+ int size_upper_limit = 0;
+ int count_upper_limit = 0;
+ HeapIterator it(CcTest::heap());
+ for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
+ size_upper_limit += obj->Size();
+ count_upper_limit++;
+ }
+
+ ContextMeasure measure(*isolate->native_context());
+
+ PrintF("Context size : %d bytes\n", measure.Size());
+ PrintF("Context object count: %d\n", measure.Count());
+
+ CHECK_LE(1000, measure.Count());
+ CHECK_LE(50000, measure.Size());
+
+ CHECK_LE(measure.Count(), count_upper_limit);
+ CHECK_LE(measure.Size(), size_upper_limit);
+}
'../../src/compiler/zone-pool.h',
'../../src/compiler.cc',
'../../src/compiler.h',
+ '../../src/context-measure.cc',
+ '../../src/context-measure.h',
'../../src/contexts.cc',
'../../src/contexts.h',
'../../src/conversions-inl.h',