Tighten up assertions checking GC-safety of stub calls.
authorvegorov@chromium.org <vegorov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 27 Sep 2011 10:53:22 +0000 (10:53 +0000)
committervegorov@chromium.org <vegorov@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 27 Sep 2011 10:53:22 +0000 (10:53 +0000)
Ensure that stubs are properly pregenerated on all platforms.

R=erik.corry@gmail.com
BUG=v8:1729

Review URL: http://codereview.chromium.org/8041035

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9447 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

12 files changed:
src/arm/code-stubs-arm.cc
src/arm/code-stubs-arm.h
src/arm/macro-assembler-arm.cc
src/code-stubs.h
src/ia32/code-stubs-ia32.cc
src/ia32/code-stubs-ia32.h
src/ia32/macro-assembler-ia32.cc
src/mips/code-stubs-mips.cc
src/mips/macro-assembler-mips.cc
src/x64/code-stubs-x64.cc
src/x64/code-stubs-x64.h
src/x64/macro-assembler-x64.cc

index eadbe074b35add62070bfb38c7f53df81a222d59..2b7c30325e8cc68d4b9d44b690ded312697f0149 100644 (file)
@@ -859,7 +859,7 @@ void FloatingPointHelper::CallCCodeForDoubleOperation(
 }
 
 
-bool WriteInt32ToHeapNumberStub::CompilingCallsToThisStubIsGCSafe() {
+bool WriteInt32ToHeapNumberStub::IsPregenerated() {
   // These variants are compiled ahead of time.  See next method.
   if (the_int_.is(r1) && the_heap_number_.is(r0) && scratch_.is(r2)) {
     return true;
@@ -2094,6 +2094,10 @@ void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(
 
 
 void BinaryOpStub::Generate(MacroAssembler* masm) {
+  // Explicitly allow generation of nested stubs. It is safe here because
+  // generation code does not use any raw pointers.
+  AllowStubCallsScope allow_stub_calls(masm, true);
+
   switch (operands_type_) {
     case BinaryOpIC::UNINITIALIZED:
       GenerateTypeTransition(masm);
@@ -3394,7 +3398,7 @@ bool CEntryStub::NeedsImmovableCode() {
 }
 
 
-bool CEntryStub::CompilingCallsToThisStubIsGCSafe() {
+bool CEntryStub::IsPregenerated() {
   return (!save_doubles_ || ISOLATE->fp_stubs_generated()) &&
           result_size_ == 1;
 }
@@ -3402,6 +3406,8 @@ bool CEntryStub::CompilingCallsToThisStubIsGCSafe() {
 
 void CodeStub::GenerateStubsAheadOfTime() {
   WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime();
+  StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime();
+  RecordWriteStub::GenerateFixedRegStubsAheadOfTime();
 }
 
 
@@ -6837,7 +6843,7 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
 };
 
 
-bool RecordWriteStub::CompilingCallsToThisStubIsGCSafe() {
+bool RecordWriteStub::IsPregenerated() {
   for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
        !entry->object.is(no_reg);
        entry++) {
index e202e1bae4466d9daf2c28637fd52d71de61ac2e..85a6a4f51b21606c4518174a834cb0931e7666ef 100644 (file)
@@ -65,7 +65,7 @@ class StoreBufferOverflowStub: public CodeStub {
 
   void Generate(MacroAssembler* masm);
 
-  virtual bool CompilingCallsToThisStubIsGCSafe() { return true; }
+  virtual bool IsPregenerated() { return true; }
   static void GenerateFixedRegStubsAheadOfTime();
   virtual bool SometimesSetsUpAFrame() { return false; }
 
@@ -342,7 +342,7 @@ class WriteInt32ToHeapNumberStub : public CodeStub {
         the_heap_number_(the_heap_number),
         scratch_(scratch) { }
 
-  bool CompilingCallsToThisStubIsGCSafe();
+  bool IsPregenerated();
   static void GenerateFixedRegStubsAheadOfTime();
 
  private:
@@ -416,7 +416,7 @@ class RecordWriteStub: public CodeStub {
     INCREMENTAL_COMPACTION
   };
 
-  virtual bool CompilingCallsToThisStubIsGCSafe();
+  virtual bool IsPregenerated();
   static void GenerateFixedRegStubsAheadOfTime();
   virtual bool SometimesSetsUpAFrame() { return false; }
 
index b3990c34b1840b4cacca851ef0fd5236f894f8d1..918907b862ac49f20663660a577e49ada1baae9e 100644 (file)
@@ -2003,7 +2003,7 @@ MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub, Condition cond) {
 
 
 void MacroAssembler::TailCallStub(CodeStub* stub, Condition cond) {
-  ASSERT(stub->CompilingCallsToThisStubIsGCSafe() || allow_stub_calls_);
+  ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
   Jump(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
 }
 
@@ -2113,7 +2113,7 @@ MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(
 
 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
   if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
-  return stub->CompilingCallsToThisStubIsGCSafe() || allow_stub_calls_;
+  return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
 }
 
 
index 42da75eba13ca73e9dc4a4c7fdc4f300be2c2829..1368bacf6deeecc42839afcfaede53cee2066bd3 100644 (file)
@@ -144,8 +144,17 @@ class CodeStub BASE_EMBEDDED {
 
   virtual ~CodeStub() {}
 
+  bool CompilingCallsToThisStubIsGCSafe() {
+    bool is_pregenerated = IsPregenerated();
+#ifdef DEBUG
+    Code* code = NULL;
+    ASSERT(!is_pregenerated || FindCodeInCache(&code));
+#endif
+    return is_pregenerated;
+  }
+
   // See comment above, where Instanceof is defined.
-  virtual bool CompilingCallsToThisStubIsGCSafe() {
+  virtual bool IsPregenerated() {
     return MajorKey() <= Instanceof;
   }
 
@@ -564,7 +573,7 @@ class CEntryStub : public CodeStub {
   // time, so it's OK to call it from other stubs that can't cope with GC during
   // their code generation.  On machines that always have gp registers (x64) we
   // can generate both variants ahead of time.
-  virtual bool CompilingCallsToThisStubIsGCSafe();
+  virtual bool IsPregenerated();
 
  private:
   void GenerateCore(MacroAssembler* masm,
index c74d3ecef4bcd794f338c17dc7edc29a9ca1400d..c998e089d961b1b8ef8a8e23b05ebe9b3614837c 100644 (file)
@@ -986,6 +986,10 @@ void BinaryOpStub::GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm) {
 
 
 void BinaryOpStub::Generate(MacroAssembler* masm) {
+  // Explicitly allow generation of nested stubs. It is safe here because
+  // generation code does not use any raw pointers.
+  AllowStubCallsScope allow_stub_calls(masm, true);
+
   switch (operands_type_) {
     case BinaryOpIC::UNINITIALIZED:
       GenerateTypeTransition(masm);
@@ -4333,13 +4337,16 @@ bool CEntryStub::NeedsImmovableCode() {
 }
 
 
-bool CEntryStub::CompilingCallsToThisStubIsGCSafe() {
+bool CEntryStub::IsPregenerated() {
   return (!save_doubles_ || ISOLATE->fp_stubs_generated()) &&
           result_size_ == 1;
 }
 
 
 void CodeStub::GenerateStubsAheadOfTime() {
+  StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime();
+  // It is important that the store buffer overflow stubs are generated first.
+  RecordWriteStub::GenerateFixedRegStubsAheadOfTime();
 }
 
 
@@ -6597,7 +6604,7 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
   // GenerateStoreField calls the stub with two different permutations of
   // registers.  This is the second.
   { ebx, ecx, edx, EMIT_REMEMBERED_SET },
-  // StoreIC::GenerateNormal via GenerateDictionaryStore.
+  // StoreIC::GenerateNormal via GenerateDictionaryStore, CompileArrayPushCall
   { ebx, edi, edx, EMIT_REMEMBERED_SET },
   // KeyedStoreIC::GenerateGeneric.
   { ebx, edx, ecx, EMIT_REMEMBERED_SET},
@@ -6608,7 +6615,7 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
 };
 
 
-bool RecordWriteStub::CompilingCallsToThisStubIsGCSafe() {
+bool RecordWriteStub::IsPregenerated() {
   for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
        !entry->object.is(no_reg);
        entry++) {
@@ -6627,8 +6634,12 @@ bool RecordWriteStub::CompilingCallsToThisStubIsGCSafe() {
 void StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime() {
   StoreBufferOverflowStub stub1(kDontSaveFPRegs);
   stub1.GetCode();
-  StoreBufferOverflowStub stub2(kSaveFPRegs);
-  stub2.GetCode();
+
+  CpuFeatures::TryForceFeatureScope scope(SSE2);
+  if (CpuFeatures::IsSupported(SSE2)) {
+    StoreBufferOverflowStub stub2(kSaveFPRegs);
+    stub2.GetCode();
+  }
 }
 
 
index ab509b7277c3ff6ff2b878f23f5a91a9b3d6e4e7..498fe57f3660681359d118ca376d251b3b47ddf9 100644 (file)
@@ -67,7 +67,7 @@ class StoreBufferOverflowStub: public CodeStub {
 
   void Generate(MacroAssembler* masm);
 
-  virtual bool CompilingCallsToThisStubIsGCSafe() { return true; }
+  virtual bool IsPregenerated() { return true; }
   static void GenerateFixedRegStubsAheadOfTime();
   virtual bool SometimesSetsUpAFrame() { return false; }
 
@@ -495,7 +495,7 @@ class RecordWriteStub: public CodeStub {
     INCREMENTAL_COMPACTION
   };
 
-  virtual bool CompilingCallsToThisStubIsGCSafe();
+  virtual bool IsPregenerated();
   static void GenerateFixedRegStubsAheadOfTime();
   virtual bool SometimesSetsUpAFrame() { return false; }
 
index 405ae516dcc2d8339a485f50acf34990bf45c8c7..2e0560d6a80dae4e656be31ae8cb853151122772 100644 (file)
@@ -1510,7 +1510,7 @@ MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub) {
 
 
 void MacroAssembler::TailCallStub(CodeStub* stub) {
-  ASSERT(stub->CompilingCallsToThisStubIsGCSafe() || allow_stub_calls_);
+  ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
   jmp(stub->GetCode(), RelocInfo::CODE_TARGET);
 }
 
@@ -1533,7 +1533,7 @@ void MacroAssembler::StubReturn(int argc) {
 
 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
   if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
-  return stub->CompilingCallsToThisStubIsGCSafe() || allow_stub_calls_;
+  return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
 }
 
 
index f64973a6e95402428ccde461f7436a981bc329af..b5ecc68ee0d4e51a98fa7f034ff76be40ffcd66a 100644 (file)
@@ -3477,7 +3477,7 @@ bool CEntryStub::NeedsImmovableCode() {
 }
 
 
-bool CEntryStub::CompilingCallsToThisStubIsGCSafe() {
+bool CEntryStub::IsPregenerated() {
   return (!save_doubles_ || ISOLATE->fp_stubs_generated()) &&
           result_size_ == 1;
 }
index fd89d576436a8ce34d6c578ad3779e24208aec21..d7732c6a381b3ddbc61534c51de4f4764f43c4aa 100644 (file)
@@ -3575,7 +3575,7 @@ MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub, Condition cond,
 
 
 void MacroAssembler::TailCallStub(CodeStub* stub) {
-  ASSERT(stub->CompilingCallsToThisStubIsGCSafe() || allow_stub_calls_);
+  ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
   Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
 }
 
@@ -3694,7 +3694,7 @@ MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(
 
 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
   if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
-  return stub->CompilingCallsToThisStubIsGCSafe() || allow_stub_calls_;
+  return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
 }
 
 
index 9813657e1a80f05c3b947268f52fa9ec82be55f8..7c94d9177ed4206d4c2dab3fdaf769065432db24 100644 (file)
@@ -773,6 +773,10 @@ void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
 
 
 void BinaryOpStub::Generate(MacroAssembler* masm) {
+  // Explicitly allow generation of nested stubs. It is safe here because
+  // generation code does not use any raw pointers.
+  AllowStubCallsScope allow_stub_calls(masm, true);
+
   switch (operands_type_) {
     case BinaryOpIC::UNINITIALIZED:
       GenerateTypeTransition(masm);
@@ -3349,7 +3353,7 @@ bool CEntryStub::NeedsImmovableCode() {
 }
 
 
-bool CEntryStub::CompilingCallsToThisStubIsGCSafe() {
+bool CEntryStub::IsPregenerated() {
   return result_size_ == 1;
 }
 
@@ -5578,7 +5582,7 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
 };
 
 
-bool RecordWriteStub::CompilingCallsToThisStubIsGCSafe() {
+bool RecordWriteStub::IsPregenerated() {
   for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime;
        !entry->object.is(no_reg);
        entry++) {
index e3be69e5072754b08e9c925fe391b1e31ac74d17..698ba403cda6d5b7db64d0d0b039c7decdfd537d 100644 (file)
@@ -66,7 +66,7 @@ class StoreBufferOverflowStub: public CodeStub {
 
   void Generate(MacroAssembler* masm);
 
-  virtual bool CompilingCallsToThisStubIsGCSafe() { return true; }
+  virtual bool IsPregenerated() { return true; }
   static void GenerateFixedRegStubsAheadOfTime();
   virtual bool SometimesSetsUpAFrame() { return false; }
 
@@ -497,7 +497,7 @@ class RecordWriteStub: public CodeStub {
     INCREMENTAL_COMPACTION
   };
 
-  virtual bool CompilingCallsToThisStubIsGCSafe();
+  virtual bool IsPregenerated();
   static void GenerateFixedRegStubsAheadOfTime();
   virtual bool SometimesSetsUpAFrame() { return false; }
 
index d586b0a4d4a73655c14319e6941155b28c2db8d5..eb4b9f1f23718343029c3b1735e88f21edb602ae 100644 (file)
@@ -508,7 +508,7 @@ MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub) {
 
 
 void MacroAssembler::TailCallStub(CodeStub* stub) {
-  ASSERT(stub->CompilingCallsToThisStubIsGCSafe() || allow_stub_calls_);
+  ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
   Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
 }
 
@@ -531,7 +531,7 @@ void MacroAssembler::StubReturn(int argc) {
 
 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
   if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
-  return stub->CompilingCallsToThisStubIsGCSafe() || allow_stub_calls_;
+  return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
 }