Reviewers: Hannes Payer,
Message:
I'll add support for other architectures if you think this looks OK.
Description:
Enable preaging of code objects for low-memory devices.
This change means that code which is never re-executed is garbage collected
more quickly (limiting heap growth), however, code which is re-executed is
reset to the young age, thus being kept around for the same number of GC
generations as currently.
Add a ResourceConstraint for the embedder to specify that V8 is running on a
memory constrained device.
This enables us to specialize certain operations such that we limit memory
usage on low-memory devices, without reducing performance on devices which
are not memory constrained.
BUG=chromium:280984
Please review this at https://codereview.chromium.org/23480031/
SVN Base: https://v8.googlecode.com/svn/trunk
Affected files (+50, -5 lines):
M src/arm/assembler-arm-inl.h
M src/arm/codegen-arm.cc
M src/arm/full-codegen-arm.cc
M src/arm/lithium-codegen-arm.cc
M src/objects.h
M src/objects.cc
Index: src/arm/assembler-arm-inl.h
diff --git a/src/arm/assembler-arm-inl.h b/src/arm/assembler-arm-inl.h
index
bfe9bc8335a384d9403512179456828b30d7526d..366730550187d668a60e25b863b7fc4d7a14202d
100644
--- a/src/arm/assembler-arm-inl.h
+++ b/src/arm/assembler-arm-inl.h
@@ -207,6 +207,9 @@ void RelocInfo::set_target_cell(Cell* cell,
WriteBarrierMode mode) {
static const int kNoCodeAgeSequenceLength = 3;
+static const int kPreAgeCodeNopType = lr.code();
+static const int kNoAgeCodeNopType = ip.code();
+
Code* RelocInfo::code_age_stub() {
ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
Index: src/arm/codegen-arm.cc
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index
7559373ee9aa89206dce3d0dff54a7b95cf9f9ae..1eec67f0cf3a1b616c8c498fad7d511b4311f612
100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -838,7 +838,27 @@ static byte* GetNoCodeAgeSequence(uint32_t* length) {
CodePatcher patcher(byte_sequence, kNoCodeAgeSequenceLength);
PredictableCodeSizeScope scope(patcher.masm(), *length);
patcher.masm()->stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() |
lr.bit());
- patcher.masm()->nop(ip.code());
+ patcher.masm()->nop(kNoAgeCodeNopType);
+ patcher.masm()->add(fp, sp, Operand(2 * kPointerSize));
+ initialized = true;
+ }
+ return byte_sequence;
+}
+
+
+static byte* GetPreAgedCodeAgeSequence(uint32_t* length) {
+ // If code is "pre-aged" then this sequence of instructions is found in
the
+ // boilerplate stack-building prologue that is found in FUNCTIONS, and is
+ // patched out for code aging.
+ static bool initialized = false;
+ static uint32_t sequence[kNoCodeAgeSequenceLength];
+ byte* byte_sequence = reinterpret_cast<byte*>(sequence);
+ *length = kNoCodeAgeSequenceLength * Assembler::kInstrSize;
+ if (!initialized) {
+ CodePatcher patcher(byte_sequence, kNoCodeAgeSequenceLength);
+ PredictableCodeSizeScope scope(patcher.masm(), *length);
+ patcher.masm()->stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() |
lr.bit());
+ patcher.masm()->nop(kPreAgeCodeNopType);
patcher.masm()->add(fp, sp, Operand(2 * kPointerSize));
initialized = true;
}
@@ -851,6 +871,18 @@ bool Code::IsYoungSequence(byte* sequence) {
byte* young_sequence = GetNoCodeAgeSequence(&young_length);
bool result = !memcmp(sequence, young_sequence, young_length);
ASSERT(result ||
+ IsPreAgedSequence(sequence) ||
+ Memory::uint32_at(sequence) == kCodeAgePatchFirstInstruction);
+ return result;
+}
+
+
+bool Code::IsPreAgedSequence(byte* sequence) {
+ uint32_t pre_aged_length;
+ byte* pre_aged_sequence = GetPreAgedCodeAgeSequence(&pre_aged_length);
+ bool result = !memcmp(sequence, pre_aged_sequence, pre_aged_length);
+ ASSERT(result ||
+ IsYoungSequence(sequence) ||
Memory::uint32_at(sequence) == kCodeAgePatchFirstInstruction);
return result;
}
@@ -861,6 +893,9 @@ void Code::GetCodeAgeAndParity(byte* sequence, Age* age,
if (IsYoungSequence(sequence)) {
*age = kNoAge;
*parity = NO_MARKING_PARITY;
+ } else if (IsPreAgedSequence(sequence)) {
+ *age = kPreAgedCodeAge;
+ *parity = NO_MARKING_PARITY;
} else {
Address target_address = Memory::Address_at(
sequence + Assembler::kInstrSize * (kNoCodeAgeSequenceLength - 1));
Index: src/arm/full-codegen-arm.cc
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index
ea7b73f2fe987fcbfde93d4a334fb1395b57bf42..9d8dfec807036da430b117791b52d7ad0a60b70d
100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -169,7 +169,9 @@ void FullCodeGenerator::Generate() {
// The following three instructions must remain together and unmodified
// for code aging to work properly.
__ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
- __ nop(ip.code());
+ // Pre-age code objects on memory constrained devices.
+ __ nop(isolate()->isMemoryConstrained() ?
+ kPreAgeCodeNopType : kNoAgeCodeNopType);
// Adjust FP to point to saved FP.
__ add(fp, sp, Operand(2 * kPointerSize));
}
Index: src/arm/lithium-codegen-arm.cc
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index
929d04de13aa693065ad37067d8645266eed2300..45c4ef5a987384fe63af6ae2ffa4f892132abe6e
100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -161,7 +161,9 @@ bool LCodeGen::GeneratePrologue() {
// The following three instructions must remain together and
unmodified
// for code aging to work properly.
__ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
- __ nop(ip.code());
+ // Pre-age code objects on low memory devices.
+ __ nop(isolate()->isMemoryConstrained() ?
+ kPreAgeCodeNopType : kNoAgeCodeNopType);
// Adjust FP to point to saved FP.
__ add(fp, sp, Operand(2 * kPointerSize));
}
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index
7839faaddf61e4234b16d6109bc9c6e1c26fde18..58d08a3ef1e2a5e03a39e1c104c4f4ed26ef0273
100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -10386,7 +10386,7 @@ bool Code::IsOld() {
Age age;
MarkingParity parity;
GetCodeAgeAndParity(sequence, &age, &parity);
- return age >= kSexagenarianCodeAge;
+ return age >= kIsOldCodeAge;
}
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index
388187445fe524bdb5aa7d6e31f0c074b51abe34..9fd6b56dc1003118593859b0f8eabd6be5cb5cd8
100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -4875,7 +4875,9 @@ class Code: public HeapObject {
CODE_AGE_LIST(DECLARE_CODE_AGE_ENUM)
kAfterLastCodeAge,
kLastCodeAge = kAfterLastCodeAge - 1,
- kCodeAgeCount = kAfterLastCodeAge - 1
+ kCodeAgeCount = kAfterLastCodeAge - 1,
+ kPreAgedCodeAge = kQuinquagenarianCodeAge,
+ kIsOldCodeAge = kSexagenarianCodeAge,
};
#undef DECLARE_CODE_AGE_ENUM
@@ -4886,6 +4888,7 @@ class Code: public HeapObject {
static void MakeCodeAgeSequenceYoung(byte* sequence);
void MakeOlder(MarkingParity);
static bool IsYoungSequence(byte* sequence);
+ static bool IsPreAgedSequence(byte* sequence);
bool IsOld();
int GetAge();
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.