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.

Reply via email to