Revision: 21165
Author:   [email protected]
Date:     Tue May  6 11:25:37 2014 UTC
Log:      Fix for 3303 MultithreadedParallelIsolates has a race condition.

The fix is to make the code aging sequence hang off the isolate.

BUG=v8:3303
[email protected]
LOG=N

Review URL: https://codereview.chromium.org/261953002
http://code.google.com/p/v8/source/detail?r=21165

Modified:
 /branches/bleeding_edge/src/arm/assembler-arm-inl.h
 /branches/bleeding_edge/src/arm/builtins-arm.cc
 /branches/bleeding_edge/src/arm/codegen-arm.cc
 /branches/bleeding_edge/src/arm/deoptimizer-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.cc
 /branches/bleeding_edge/src/arm64/assembler-arm64-inl.h
 /branches/bleeding_edge/src/arm64/builtins-arm64.cc
 /branches/bleeding_edge/src/arm64/codegen-arm64.cc
 /branches/bleeding_edge/src/arm64/macro-assembler-arm64.cc
 /branches/bleeding_edge/src/arm64/macro-assembler-arm64.h
 /branches/bleeding_edge/src/assembler.cc
 /branches/bleeding_edge/src/assembler.h
 /branches/bleeding_edge/src/codegen.h
 /branches/bleeding_edge/src/ia32/codegen-ia32.cc
 /branches/bleeding_edge/src/isolate.cc
 /branches/bleeding_edge/src/isolate.h
 /branches/bleeding_edge/src/objects-debug.cc
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/x64/codegen-x64.cc
 /branches/bleeding_edge/test/cctest/cctest.status

=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm-inl.h Fri Apr 25 11:00:37 2014 UTC +++ /branches/bleeding_edge/src/arm/assembler-arm-inl.h Tue May 6 11:25:37 2014 UTC
@@ -222,7 +222,7 @@
 }


-static const int kNoCodeAgeSequenceLength = 3;
+static const int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize;


 Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) {
@@ -234,15 +234,15 @@
 Code* RelocInfo::code_age_stub() {
   ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
   return Code::GetCodeFromTargetAddress(
-      Memory::Address_at(pc_ + Assembler::kInstrSize *
-                         (kNoCodeAgeSequenceLength - 1)));
+      Memory::Address_at(pc_ +
+ (kNoCodeAgeSequenceLength - Assembler::kInstrSize)));
 }


 void RelocInfo::set_code_age_stub(Code* stub) {
   ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
-  Memory::Address_at(pc_ + Assembler::kInstrSize *
-                     (kNoCodeAgeSequenceLength - 1)) =
+  Memory::Address_at(pc_ +
+                     (kNoCodeAgeSequenceLength - Assembler::kInstrSize)) =
       stub->instruction_start();
 }

=======================================
--- /branches/bleeding_edge/src/arm/builtins-arm.cc Wed Apr 30 14:33:35 2014 UTC +++ /branches/bleeding_edge/src/arm/builtins-arm.cc Tue May 6 11:25:37 2014 UTC
@@ -898,7 +898,7 @@
   __ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));

   // Jump to point after the code-age stub.
- __ add(r0, r0, Operand(kNoCodeAgeSequenceLength * Assembler::kInstrSize));
+  __ add(r0, r0, Operand(kNoCodeAgeSequenceLength));
   __ mov(pc, r0);
 }

=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc Fri May 2 10:14:37 2014 UTC +++ /branches/bleeding_edge/src/arm/codegen-arm.cc Tue May 6 11:25:37 2014 UTC
@@ -822,47 +822,46 @@
 static const uint32_t kCodeAgePatchFirstInstruction = 0xe24f0008;
 #endif

-static byte* GetNoCodeAgeSequence(uint32_t* length) {
-  // The sequence of instructions that is patched out for aging code is the
- // following boilerplate stack-building prologue that is found in FUNCTIONS
-  static bool initialized = false;
-  static uint32_t sequence[kNoCodeAgeSequenceLength];
-  byte* byte_sequence = reinterpret_cast<byte*>(sequence);
-  *length = kNoCodeAgeSequenceLength * Assembler::kInstrSize;
-  if (!initialized) {
- // Since patcher is a large object, allocate it dynamically when needed,
-    // to avoid overloading the stack in stress conditions.
-    SmartPointer<CodePatcher>
-        patcher(new CodePatcher(byte_sequence, kNoCodeAgeSequenceLength));
-    PredictableCodeSizeScope scope(patcher->masm(), *length);
-    patcher->masm()->PushFixedFrame(r1);
-    patcher->masm()->nop(ip.code());
-    patcher->masm()->add(
-        fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
-    initialized = true;
-  }
-  return byte_sequence;
+CodeAgingHelper::CodeAgingHelper() {
+  ASSERT(young_sequence_.length() == kNoCodeAgeSequenceLength);
+  // Since patcher is a large object, allocate it dynamically when needed,
+  // to avoid overloading the stack in stress conditions.
+  // DONT_FLUSH is used because the CodeAgingHelper is initialized early in
+  // the process, before ARM simulator ICache is setup.
+  SmartPointer<CodePatcher> patcher(
+      new CodePatcher(young_sequence_.start(),
+                      young_sequence_.length() / Assembler::kInstrSize,
+                      CodePatcher::DONT_FLUSH));
+ PredictableCodeSizeScope scope(patcher->masm(), young_sequence_.length());
+  patcher->masm()->PushFixedFrame(r1);
+  patcher->masm()->nop(ip.code());
+  patcher->masm()->add(
+      fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
+}
+
+
+#ifdef DEBUG
+bool CodeAgingHelper::IsOld(byte* candidate) const {
+  return Memory::uint32_at(candidate) == kCodeAgePatchFirstInstruction;
 }
+#endif


-bool Code::IsYoungSequence(byte* sequence) {
-  uint32_t young_length;
-  byte* young_sequence = GetNoCodeAgeSequence(&young_length);
-  bool result = !memcmp(sequence, young_sequence, young_length);
-  ASSERT(result ||
-         Memory::uint32_at(sequence) == kCodeAgePatchFirstInstruction);
+bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
+  bool result = isolate->code_aging_helper()->IsYoung(sequence);
+  ASSERT(result || isolate->code_aging_helper()->IsOld(sequence));
   return result;
 }


-void Code::GetCodeAgeAndParity(byte* sequence, Age* age,
+void Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
                                MarkingParity* parity) {
-  if (IsYoungSequence(sequence)) {
+  if (IsYoungSequence(isolate, sequence)) {
     *age = kNoAgeCodeAge;
     *parity = NO_MARKING_PARITY;
   } else {
     Address target_address = Memory::Address_at(
-        sequence + Assembler::kInstrSize * (kNoCodeAgeSequenceLength - 1));
+        sequence + (kNoCodeAgeSequenceLength - Assembler::kInstrSize));
     Code* stub = GetCodeFromTargetAddress(target_address);
     GetCodeAgeAndParity(stub, age, parity);
   }
@@ -873,10 +872,9 @@
                                 byte* sequence,
                                 Code::Age age,
                                 MarkingParity parity) {
-  uint32_t young_length;
-  byte* young_sequence = GetNoCodeAgeSequence(&young_length);
+ uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
   if (age == kNoAgeCodeAge) {
-    CopyBytes(sequence, young_sequence, young_length);
+    isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
     CPU::FlushICache(sequence, young_length);
   } else {
     Code* stub = GetCodeAgeStub(isolate, age, parity);
=======================================
--- /branches/bleeding_edge/src/arm/deoptimizer-arm.cc Wed Apr 30 09:50:58 2014 UTC +++ /branches/bleeding_edge/src/arm/deoptimizer-arm.cc Tue May 6 11:25:37 2014 UTC
@@ -31,7 +31,7 @@
     // Fail hard and early if we enter this code object again.
     byte* pointer = code->FindCodeAgeSequence();
     if (pointer != NULL) {
-      pointer += kNoCodeAgeSequenceLength * Assembler::kInstrSize;
+      pointer += kNoCodeAgeSequenceLength;
     } else {
       pointer = code->instruction_start();
     }
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Tue May 6 09:28:08 2014 UTC +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Tue May 6 11:25:37 2014 UTC
@@ -910,7 +910,7 @@
     add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
   } else {
     PredictableCodeSizeScope predictible_code_size_scope(
-        this, kNoCodeAgeSequenceLength * Assembler::kInstrSize);
+        this, kNoCodeAgeSequenceLength);
     // The following three instructions must remain together and unmodified
     // for code aging to work properly.
     if (isolate()->IsCodePreAgingActive()) {
=======================================
--- /branches/bleeding_edge/src/arm64/assembler-arm64-inl.h Tue Apr 29 06:42:26 2014 UTC +++ /branches/bleeding_edge/src/arm64/assembler-arm64-inl.h Tue May 6 11:25:37 2014 UTC
@@ -715,7 +715,7 @@
 }


-static const int kCodeAgeSequenceSize = 5 * kInstructionSize;
+static const int kNoCodeAgeSequenceLength = 5 * kInstructionSize;
 static const int kCodeAgeStubEntryOffset = 3 * kInstructionSize;


@@ -727,7 +727,6 @@

 Code* RelocInfo::code_age_stub() {
   ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
-  ASSERT(!Code::IsYoungSequence(pc_));
   // Read the stub entry point from the code age sequence.
   Address stub_entry_address = pc_ + kCodeAgeStubEntryOffset;
return Code::GetCodeFromTargetAddress(Memory::Address_at(stub_entry_address));
@@ -736,7 +735,7 @@

 void RelocInfo::set_code_age_stub(Code* stub) {
   ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
-  ASSERT(!Code::IsYoungSequence(pc_));
+  ASSERT(!Code::IsYoungSequence(stub->GetIsolate(), pc_));
// Overwrite the stub entry point in the code age sequence. This is loaded as
   // a literal so there is no need to call FlushICache here.
   Address stub_entry_address = pc_ + kCodeAgeStubEntryOffset;
=======================================
--- /branches/bleeding_edge/src/arm64/builtins-arm64.cc Wed Apr 30 14:33:35 2014 UTC +++ /branches/bleeding_edge/src/arm64/builtins-arm64.cc Tue May 6 11:25:37 2014 UTC
@@ -887,7 +887,7 @@
   }

   // Jump to point after the code-age stub.
-  __ Add(x0, x0, kCodeAgeSequenceSize);
+  __ Add(x0, x0, kNoCodeAgeSequenceLength);
   __ Br(x0);
 }

=======================================
--- /branches/bleeding_edge/src/arm64/codegen-arm64.cc Tue Apr 29 06:42:26 2014 UTC +++ /branches/bleeding_edge/src/arm64/codegen-arm64.cc Tue May 6 11:25:37 2014 UTC
@@ -350,14 +350,41 @@
 }


-bool Code::IsYoungSequence(byte* sequence) {
-  return MacroAssembler::IsYoungSequence(sequence);
+CodeAgingHelper::CodeAgingHelper() {
+  ASSERT(young_sequence_.length() == kNoCodeAgeSequenceLength);
+  // The sequence of instructions that is patched out for aging code is the
+  // following boilerplate stack-building prologue that is found both in
+  // FUNCTION and OPTIMIZED_FUNCTION code:
+  PatchingAssembler patcher(young_sequence_.start(),
+                            young_sequence_.length() / kInstructionSize);
+ // The young sequence is the frame setup code for FUNCTION code types. It is
+  // generated by FullCodeGenerator::Generate.
+  MacroAssembler::EmitFrameSetupForCodeAgePatching(&patcher);
+
+#ifdef DEBUG
+  const int length = kCodeAgeStubEntryOffset / kInstructionSize;
+  ASSERT(old_sequence_.length() >= kCodeAgeStubEntryOffset);
+  PatchingAssembler patcher_old(old_sequence_.start(), length);
+  MacroAssembler::EmitCodeAgeSequence(&patcher_old, NULL);
+#endif
 }


-void Code::GetCodeAgeAndParity(byte* sequence, Age* age,
+#ifdef DEBUG
+bool CodeAgingHelper::IsOld(byte* candidate) const {
+ return memcmp(candidate, old_sequence_.start(), kCodeAgeStubEntryOffset) == 0;
+}
+#endif
+
+
+bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
+  return MacroAssembler::IsYoungSequence(isolate, sequence);
+}
+
+
+void Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
                                MarkingParity* parity) {
-  if (IsYoungSequence(sequence)) {
+  if (IsYoungSequence(isolate, sequence)) {
     *age = kNoAgeCodeAge;
     *parity = NO_MARKING_PARITY;
   } else {
@@ -372,7 +399,8 @@
                                 byte* sequence,
                                 Code::Age age,
                                 MarkingParity parity) {
- PatchingAssembler patcher(sequence, kCodeAgeSequenceSize / kInstructionSize);
+  PatchingAssembler patcher(sequence,
+                            kNoCodeAgeSequenceLength / kInstructionSize);
   if (age == kNoAgeCodeAge) {
     MacroAssembler::EmitFrameSetupForCodeAgePatching(&patcher);
   } else {
=======================================
--- /branches/bleeding_edge/src/arm64/macro-assembler-arm64.cc Tue May 6 09:28:08 2014 UTC +++ /branches/bleeding_edge/src/arm64/macro-assembler-arm64.cc Tue May 6 11:25:37 2014 UTC
@@ -5067,7 +5067,8 @@
// TODO(jbramley): Other architectures use the internal memcpy to copy the // sequence. If this is a performance bottleneck, we should consider caching
   // the sequence and copying it in the same way.
- InstructionAccurateScope scope(this, kCodeAgeSequenceSize / kInstructionSize);
+  InstructionAccurateScope scope(this,
+ kNoCodeAgeSequenceLength / kInstructionSize);
   ASSERT(jssp.Is(StackPointer()));
   EmitFrameSetupForCodeAgePatching(this);
 }
@@ -5075,7 +5076,8 @@


 void MacroAssembler::EmitCodeAgeSequence(Code* stub) {
- InstructionAccurateScope scope(this, kCodeAgeSequenceSize / kInstructionSize);
+  InstructionAccurateScope scope(this,
+ kNoCodeAgeSequenceLength / kInstructionSize);
   ASSERT(jssp.Is(StackPointer()));
   EmitCodeAgeSequence(this, stub);
 }
@@ -5099,7 +5101,7 @@
   __ stp(fp, lr, MemOperand(jssp, 2 * kXRegSize));
   __ add(fp, jssp, StandardFrameConstants::kFixedFrameSizeFromFp);

-  __ AssertSizeOfCodeGeneratedSince(&start, kCodeAgeSequenceSize);
+  __ AssertSizeOfCodeGeneratedSince(&start, kNoCodeAgeSequenceLength);
 }


@@ -5122,46 +5124,17 @@
   __ AssertSizeOfCodeGeneratedSince(&start, kCodeAgeStubEntryOffset);
   if (stub) {
     __ dc64(reinterpret_cast<uint64_t>(stub->instruction_start()));
-    __ AssertSizeOfCodeGeneratedSince(&start, kCodeAgeSequenceSize);
+    __ AssertSizeOfCodeGeneratedSince(&start, kNoCodeAgeSequenceLength);
   }
 }


-bool MacroAssembler::IsYoungSequence(byte* sequence) {
-  // Generate a young sequence to compare with.
-  const int length = kCodeAgeSequenceSize / kInstructionSize;
-  static bool initialized = false;
-  static byte young[kCodeAgeSequenceSize];
-  if (!initialized) {
-    PatchingAssembler patcher(young, length);
- // The young sequence is the frame setup code for FUNCTION code types. It is
-    // generated by FullCodeGenerator::Generate.
-    MacroAssembler::EmitFrameSetupForCodeAgePatching(&patcher);
-    initialized = true;
-  }
-
-  bool is_young = (memcmp(sequence, young, kCodeAgeSequenceSize) == 0);
-  ASSERT(is_young || IsCodeAgeSequence(sequence));
+bool MacroAssembler::IsYoungSequence(Isolate* isolate, byte* sequence) {
+  bool is_young = isolate->code_aging_helper()->IsYoung(sequence);
+  ASSERT(is_young ||
+         isolate->code_aging_helper()->IsOld(sequence));
   return is_young;
 }
-
-
-#ifdef DEBUG
-bool MacroAssembler::IsCodeAgeSequence(byte* sequence) {
- // The old sequence varies depending on the code age. However, the code up - // until kCodeAgeStubEntryOffset does not change, so we can check that part to
-  // get a reasonable level of verification.
-  const int length = kCodeAgeStubEntryOffset / kInstructionSize;
-  static bool initialized = false;
-  static byte old[kCodeAgeStubEntryOffset];
-  if (!initialized) {
-    PatchingAssembler patcher(old, length);
-    MacroAssembler::EmitCodeAgeSequence(&patcher, NULL);
-    initialized = true;
-  }
-  return memcmp(sequence, old, kCodeAgeStubEntryOffset) == 0;
-}
-#endif


 void MacroAssembler::TruncatingDiv(Register result,
=======================================
--- /branches/bleeding_edge/src/arm64/macro-assembler-arm64.h Tue May 6 08:05:27 2014 UTC +++ /branches/bleeding_edge/src/arm64/macro-assembler-arm64.h Tue May 6 11:25:37 2014 UTC
@@ -1987,13 +1987,7 @@
   // Return true if the sequence is a young sequence geneated by
// EmitFrameSetupForCodeAgePatching. Otherwise, this method asserts that the
   // sequence is a code age sequence (emitted by EmitCodeAgeSequence).
-  static bool IsYoungSequence(byte* sequence);
-
-#ifdef DEBUG
-  // Return true if the sequence is a code age sequence generated by
-  // EmitCodeAgeSequence.
-  static bool IsCodeAgeSequence(byte* sequence);
-#endif
+  static bool IsYoungSequence(Isolate* isolate, byte* sequence);

   // Jumps to found label if a prototype map has dictionary elements.
   void JumpIfDictionaryInPrototypeChain(Register object, Register scratch0,
=======================================
--- /branches/bleeding_edge/src/assembler.cc    Wed Apr 30 09:50:58 2014 UTC
+++ /branches/bleeding_edge/src/assembler.cc    Tue May  6 11:25:37 2014 UTC
@@ -724,7 +724,10 @@
   last_id_ = 0;
   last_position_ = 0;
   byte* sequence = code->FindCodeAgeSequence();
-  if (sequence != NULL && !Code::IsYoungSequence(sequence)) {
+  // We get the isolate from the map, because at serialization time
+  // the code pointer has been cloned and isn't really in heap space.
+  Isolate* isolate = code->map()->GetIsolate();
+  if (sequence != NULL && !Code::IsYoungSequence(isolate, sequence)) {
     code_age_sequence_ = sequence;
   } else {
     code_age_sequence_ = NULL;
@@ -856,7 +859,7 @@


 #ifdef VERIFY_HEAP
-void RelocInfo::Verify() {
+void RelocInfo::Verify(Isolate* isolate) {
   switch (rmode_) {
     case EMBEDDED_OBJECT:
       Object::VerifyPointer(target_object());
@@ -873,7 +876,7 @@
       CHECK(addr != NULL);
       // Check that we can find the right code object.
       Code* code = Code::GetCodeFromTargetAddress(addr);
-      Object* found = code->GetIsolate()->FindCodeObject(addr);
+      Object* found = isolate->FindCodeObject(addr);
       CHECK(found->IsCode());
       CHECK(code->address() == HeapObject::cast(found)->address());
       break;
@@ -895,7 +898,7 @@
       UNREACHABLE();
       break;
     case CODE_AGE_SEQUENCE:
-      ASSERT(Code::IsYoungSequence(pc_) || code_age_stub()->IsCode());
+ ASSERT(Code::IsYoungSequence(isolate, pc_) || code_age_stub()->IsCode());
       break;
   }
 }
=======================================
--- /branches/bleeding_edge/src/assembler.h     Wed Apr 30 12:25:18 2014 UTC
+++ /branches/bleeding_edge/src/assembler.h     Tue May  6 11:25:37 2014 UTC
@@ -520,7 +520,7 @@
   void Print(Isolate* isolate, FILE* out);
 #endif  // ENABLE_DISASSEMBLER
 #ifdef VERIFY_HEAP
-  void Verify();
+  void Verify(Isolate* isolate);
 #endif

   static const int kCodeTargetMask = (1 << (LAST_CODE_ENUM + 1)) - 1;
=======================================
--- /branches/bleeding_edge/src/codegen.h       Tue May  6 11:14:37 2014 UTC
+++ /branches/bleeding_edge/src/codegen.h       Tue May  6 11:25:37 2014 UTC
@@ -130,6 +130,33 @@
 static const int kNumberDictionaryProbes = 4;


+class CodeAgingHelper {
+ public:
+  CodeAgingHelper();
+
+ uint32_t young_sequence_length() const { return young_sequence_.length(); }
+  bool IsYoung(byte* candidate) const {
+    return memcmp(candidate,
+                  young_sequence_.start(),
+                  young_sequence_.length()) == 0;
+  }
+  void CopyYoungSequenceTo(byte* new_buffer) const {
+ CopyBytes(new_buffer, young_sequence_.start(), young_sequence_.length());
+  }
+
+#ifdef DEBUG
+  bool IsOld(byte* candidate) const;
+#endif
+
+ protected:
+  const EmbeddedVector<byte, kNoCodeAgeSequenceLength> young_sequence_;
+#ifdef DEBUG
+#ifdef V8_TARGET_ARCH_ARM64
+  const EmbeddedVector<byte, kNoCodeAgeSequenceLength> old_sequence_;
+#endif
+#endif
+};
+
 } }  // namespace v8::internal

 #endif  // V8_CODEGEN_H_
=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue Apr 29 06:42:26 2014 UTC +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Tue May 6 11:25:37 2014 UTC
@@ -1050,37 +1050,33 @@
 #undef __


-static byte* GetNoCodeAgeSequence(uint32_t* length) {
-  static bool initialized = false;
-  static byte sequence[kNoCodeAgeSequenceLength];
-  *length = kNoCodeAgeSequenceLength;
-  if (!initialized) {
- // The sequence of instructions that is patched out for aging code is the
-    // following boilerplate stack-building prologue that is found both in
-    // FUNCTION and OPTIMIZED_FUNCTION code:
-    CodePatcher patcher(sequence, kNoCodeAgeSequenceLength);
-    patcher.masm()->push(ebp);
-    patcher.masm()->mov(ebp, esp);
-    patcher.masm()->push(esi);
-    patcher.masm()->push(edi);
-    initialized = true;
-  }
-  return sequence;
+CodeAgingHelper::CodeAgingHelper() {
+  ASSERT(young_sequence_.length() == kNoCodeAgeSequenceLength);
+  CodePatcher patcher(young_sequence_.start(), young_sequence_.length());
+  patcher.masm()->push(ebp);
+  patcher.masm()->mov(ebp, esp);
+  patcher.masm()->push(esi);
+  patcher.masm()->push(edi);
+}
+
+
+#ifdef DEBUG
+bool CodeAgingHelper::IsOld(byte* candidate) const {
+  return *candidate == kCallOpcode;
 }
+#endif


-bool Code::IsYoungSequence(byte* sequence) {
-  uint32_t young_length;
-  byte* young_sequence = GetNoCodeAgeSequence(&young_length);
-  bool result = (!memcmp(sequence, young_sequence, young_length));
-  ASSERT(result || *sequence == kCallOpcode);
+bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
+  bool result = isolate->code_aging_helper()->IsYoung(sequence);
+  ASSERT(result || isolate->code_aging_helper()->IsOld(sequence));
   return result;
 }


-void Code::GetCodeAgeAndParity(byte* sequence, Age* age,
+void Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
                                MarkingParity* parity) {
-  if (IsYoungSequence(sequence)) {
+  if (IsYoungSequence(isolate, sequence)) {
     *age = kNoAgeCodeAge;
     *parity = NO_MARKING_PARITY;
   } else {
@@ -1097,10 +1093,9 @@
                                 byte* sequence,
                                 Code::Age age,
                                 MarkingParity parity) {
-  uint32_t young_length;
-  byte* young_sequence = GetNoCodeAgeSequence(&young_length);
+ uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
   if (age == kNoAgeCodeAge) {
-    CopyBytes(sequence, young_sequence, young_length);
+    isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
     CPU::FlushICache(sequence, young_length);
   } else {
     Code* stub = GetCodeAgeStub(isolate, age, parity);
=======================================
--- /branches/bleeding_edge/src/isolate.cc      Mon May  5 07:10:38 2014 UTC
+++ /branches/bleeding_edge/src/isolate.cc      Tue May  6 11:25:37 2014 UTC
@@ -133,8 +133,8 @@
       per_thread = new PerIsolateThreadData(this, thread_id);
       thread_data_table_->Insert(per_thread);
     }
+    ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread);
   }
-  ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread);
   return per_thread;
 }

@@ -1425,6 +1425,7 @@
       logger_(NULL),
       stats_table_(NULL),
       stub_cache_(NULL),
+      code_aging_helper_(NULL),
       deoptimizer_data_(NULL),
       materialized_object_store_(NULL),
       capture_stack_trace_for_uncaught_exceptions_(false),
@@ -1660,6 +1661,8 @@

   delete stub_cache_;
   stub_cache_ = NULL;
+  delete code_aging_helper_;
+  code_aging_helper_ = NULL;
   delete stats_table_;
   stats_table_ = NULL;

@@ -1834,6 +1837,8 @@
 #endif
 #endif

+  code_aging_helper_ = new CodeAgingHelper();
+
   { // NOLINT
// Ensure that the thread has a valid stack guard. The v8::Locker object // will ensure this too, but we don't have to use lockers if we are only
=======================================
--- /branches/bleeding_edge/src/isolate.h       Mon May  5 07:10:38 2014 UTC
+++ /branches/bleeding_edge/src/isolate.h       Tue May  6 11:25:37 2014 UTC
@@ -54,6 +54,7 @@
 class InnerPointerToCodeCache;
 class MaterializedObjectStore;
 class NoAllocationStringAllocator;
+class CodeAgingHelper;
 class RandomNumberGenerator;
 class RegExpStack;
 class SaveContext;
@@ -836,6 +837,7 @@
   Heap* heap() { return &heap_; }
   StatsTable* stats_table();
   StubCache* stub_cache() { return stub_cache_; }
+  CodeAgingHelper* code_aging_helper() { return code_aging_helper_; }
   DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; }
   ThreadLocalTop* thread_local_top() { return &thread_local_top_; }
   MaterializedObjectStore* materialized_object_store() {
@@ -1197,6 +1199,7 @@
   StackGuard stack_guard_;
   StatsTable* stats_table_;
   StubCache* stub_cache_;
+  CodeAgingHelper* code_aging_helper_;
   DeoptimizerData* deoptimizer_data_;
   MaterializedObjectStore* materialized_object_store_;
   ThreadLocalTop thread_local_top_;
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Fri May 2 10:27:12 2014 UTC +++ /branches/bleeding_edge/src/objects-debug.cc Tue May 6 11:25:37 2014 UTC
@@ -627,8 +627,9 @@
                   kCodeAlignment));
   relocation_info()->ObjectVerify();
   Address last_gc_pc = NULL;
+  Isolate* isolate = GetIsolate();
   for (RelocIterator it(this); !it.done(); it.next()) {
-    it.rinfo()->Verify();
+    it.rinfo()->Verify(isolate);
     // Ensure that GC will not iterate twice over the same pointer.
     if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
       CHECK(it.rinfo()->pc() != last_gc_pc);
=======================================
--- /branches/bleeding_edge/src/objects.cc      Tue May  6 08:34:48 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc      Tue May  6 11:25:37 2014 UTC
@@ -11291,10 +11291,11 @@
   if (sequence != NULL) {
     Age age;
     MarkingParity code_parity;
-    GetCodeAgeAndParity(sequence, &age, &code_parity);
+    Isolate* isolate = GetIsolate();
+    GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
     age = EffectiveAge(age);
     if (age != kLastCodeAge && code_parity != current_parity) {
-      PatchPlatformCodeAge(GetIsolate(),
+      PatchPlatformCodeAge(isolate,
                            sequence,
                            static_cast<Age>(age + 1),
                            current_parity);
@@ -11330,7 +11331,7 @@
   }
   Age age;
   MarkingParity parity;
-  GetCodeAgeAndParity(sequence, &age, &parity);
+  GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
   return age;
 }

=======================================
--- /branches/bleeding_edge/src/objects.h       Tue May  6 08:05:27 2014 UTC
+++ /branches/bleeding_edge/src/objects.h       Tue May  6 11:25:37 2014 UTC
@@ -5625,7 +5625,7 @@
   static void MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate);
   static void MarkCodeAsExecuted(byte* sequence, Isolate* isolate);
   void MakeOlder(MarkingParity);
-  static bool IsYoungSequence(byte* sequence);
+  static bool IsYoungSequence(Isolate* isolate, byte* sequence);
   bool IsOld();
   Age GetAge();
   // Gets the raw code age, including psuedo code-age values such as
@@ -5787,7 +5787,7 @@
   byte* FindCodeAgeSequence();
   static void GetCodeAgeAndParity(Code* code, Age* age,
                                   MarkingParity* parity);
-  static void GetCodeAgeAndParity(byte* sequence, Age* age,
+ static void GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
                                   MarkingParity* parity);
static Code* GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity);

=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc Wed Apr 30 08:38:20 2014 UTC +++ /branches/bleeding_edge/src/x64/codegen-x64.cc Tue May 6 11:25:37 2014 UTC
@@ -616,37 +616,36 @@
 #undef __


-static byte* GetNoCodeAgeSequence(uint32_t* length) {
-  static bool initialized = false;
-  static byte sequence[kNoCodeAgeSequenceLength];
-  *length = kNoCodeAgeSequenceLength;
-  if (!initialized) {
- // The sequence of instructions that is patched out for aging code is the
-    // following boilerplate stack-building prologue that is found both in
-    // FUNCTION and OPTIMIZED_FUNCTION code:
-    CodePatcher patcher(sequence, kNoCodeAgeSequenceLength);
-    patcher.masm()->pushq(rbp);
-    patcher.masm()->movp(rbp, rsp);
-    patcher.masm()->Push(rsi);
-    patcher.masm()->Push(rdi);
-    initialized = true;
-  }
-  return sequence;
+CodeAgingHelper::CodeAgingHelper() {
+  ASSERT(young_sequence_.length() == kNoCodeAgeSequenceLength);
+  // The sequence of instructions that is patched out for aging code is the
+  // following boilerplate stack-building prologue that is found both in
+  // FUNCTION and OPTIMIZED_FUNCTION code:
+  CodePatcher patcher(young_sequence_.start(), young_sequence_.length());
+  patcher.masm()->pushq(rbp);
+  patcher.masm()->movp(rbp, rsp);
+  patcher.masm()->Push(rsi);
+  patcher.masm()->Push(rdi);
+}
+
+
+#ifdef DEBUG
+bool CodeAgingHelper::IsOld(byte* candidate) const {
+  return *candidate == kCallOpcode;
 }
+#endif


-bool Code::IsYoungSequence(byte* sequence) {
-  uint32_t young_length;
-  byte* young_sequence = GetNoCodeAgeSequence(&young_length);
-  bool result = (!memcmp(sequence, young_sequence, young_length));
-  ASSERT(result || *sequence == kCallOpcode);
+bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
+  bool result = isolate->code_aging_helper()->IsYoung(sequence);
+  ASSERT(result || isolate->code_aging_helper()->IsOld(sequence));
   return result;
 }


-void Code::GetCodeAgeAndParity(byte* sequence, Age* age,
+void Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
                                MarkingParity* parity) {
-  if (IsYoungSequence(sequence)) {
+  if (IsYoungSequence(isolate, sequence)) {
     *age = kNoAgeCodeAge;
     *parity = NO_MARKING_PARITY;
   } else {
@@ -663,10 +662,9 @@
                                 byte* sequence,
                                 Code::Age age,
                                 MarkingParity parity) {
-  uint32_t young_length;
-  byte* young_sequence = GetNoCodeAgeSequence(&young_length);
+ uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
   if (age == kNoAgeCodeAge) {
-    CopyBytes(sequence, young_sequence, young_length);
+    isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
     CPU::FlushICache(sequence, young_length);
   } else {
     Code* stub = GetCodeAgeStub(isolate, age, parity);
=======================================
--- /branches/bleeding_edge/test/cctest/cctest.status Mon May 5 13:56:39 2014 UTC +++ /branches/bleeding_edge/test/cctest/cctest.status Tue May 6 11:25:37 2014 UTC
@@ -30,9 +30,6 @@
   # All tests prefixed with 'Bug' are expected to fail.
   'test-api/Bug*': [FAIL],

-  # BUG(3303). Crashes on mac builds, known race condition.
-  'test-lockers/MultithreadedParallelIsolates': [SKIP],
-
##############################################################################
   # BUG(382): Weird test. Can't guarantee that it never times out.
   'test-api/ApplyInterruption': [PASS, TIMEOUT],

--
--
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/d/optout.

Reply via email to