forked from mirrors/gecko-dev
		
	Bug 1341937 - Part 13: Check eliding post write barriers is correct. r=jandem
Add a debug-only check that it's okay to elide the post write barriers. Differential Revision: https://phabricator.services.mozilla.com/D156789
This commit is contained in:
		
							parent
							
								
									90636aeb84
								
							
						
					
					
						commit
						1260414bfd
					
				
					 5 changed files with 93 additions and 0 deletions
				
			
		|  | @ -5084,6 +5084,22 @@ void CodeGenerator::visitPostWriteElementBarrierV( | ||||||
|   visitPostWriteBarrierCommonV(lir, ool); |   visitPostWriteBarrierCommonV(lir, ool); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void CodeGenerator::visitAssertCanElidePostWriteBarrier( | ||||||
|  |     LAssertCanElidePostWriteBarrier* lir) { | ||||||
|  |   Register object = ToRegister(lir->object()); | ||||||
|  |   ValueOperand value = | ||||||
|  |       ToValue(lir, LAssertCanElidePostWriteBarrier::ValueIndex); | ||||||
|  |   Register temp = ToRegister(lir->temp0()); | ||||||
|  | 
 | ||||||
|  |   Label ok; | ||||||
|  |   masm.branchPtrInNurseryChunk(Assembler::Equal, object, temp, &ok); | ||||||
|  |   masm.branchValueIsNurseryCell(Assembler::NotEqual, value, temp, &ok); | ||||||
|  | 
 | ||||||
|  |   masm.assumeUnreachable("Unexpected missing post write barrier"); | ||||||
|  | 
 | ||||||
|  |   masm.bind(&ok); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void CodeGenerator::visitCallNative(LCallNative* call) { | void CodeGenerator::visitCallNative(LCallNative* call) { | ||||||
|   WrappedFunction* target = call->getSingleTarget(); |   WrappedFunction* target = call->getSingleTarget(); | ||||||
|   MOZ_ASSERT(target); |   MOZ_ASSERT(target); | ||||||
|  |  | ||||||
|  | @ -2359,6 +2359,13 @@ | ||||||
|   num_temps: 1 |   num_temps: 1 | ||||||
|   mir_op: PostWriteElementBarrier |   mir_op: PostWriteElementBarrier | ||||||
| 
 | 
 | ||||||
|  | # Assert in debug mode that a post write barrier can be elided. | ||||||
|  | - name: AssertCanElidePostWriteBarrier | ||||||
|  |   operands: | ||||||
|  |     object: WordSized | ||||||
|  |     value: BoxedValue | ||||||
|  |   num_temps: 1 | ||||||
|  | 
 | ||||||
| # Guard against an object's identity. | # Guard against an object's identity. | ||||||
| - name: GuardObjectIdentity | - name: GuardObjectIdentity | ||||||
|   operands: |   operands: | ||||||
|  |  | ||||||
|  | @ -3389,6 +3389,13 @@ void LIRGenerator::visitPostWriteElementBarrier(MPostWriteElementBarrier* ins) { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void LIRGenerator::visitAssertCanElidePostWriteBarrier( | ||||||
|  |     MAssertCanElidePostWriteBarrier* ins) { | ||||||
|  |   auto* lir = new (alloc()) LAssertCanElidePostWriteBarrier( | ||||||
|  |       useRegister(ins->object()), useBox(ins->value()), temp()); | ||||||
|  |   add(lir, ins); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void LIRGenerator::visitArrayLength(MArrayLength* ins) { | void LIRGenerator::visitArrayLength(MArrayLength* ins) { | ||||||
|   MOZ_ASSERT(ins->elements()->type() == MIRType::Elements); |   MOZ_ASSERT(ins->elements()->type() == MIRType::Elements); | ||||||
|   auto* lir = new (alloc()) LArrayLength(useRegisterAtStart(ins->elements())); |   auto* lir = new (alloc()) LArrayLength(useRegisterAtStart(ins->elements())); | ||||||
|  |  | ||||||
|  | @ -1985,6 +1985,14 @@ | ||||||
| - name: PostWriteElementBarrier | - name: PostWriteElementBarrier | ||||||
|   gen_boilerplate: false |   gen_boilerplate: false | ||||||
| 
 | 
 | ||||||
|  | - name: AssertCanElidePostWriteBarrier | ||||||
|  |   operands: | ||||||
|  |     object: Object | ||||||
|  |     value: Value | ||||||
|  |   result_type: None | ||||||
|  |   guard: true | ||||||
|  |   alias_set: none | ||||||
|  | 
 | ||||||
| - name: NewNamedLambdaObject | - name: NewNamedLambdaObject | ||||||
|   arguments: |   arguments: | ||||||
|     templateObj: NamedLambdaObject* |     templateObj: NamedLambdaObject* | ||||||
|  |  | ||||||
|  | @ -327,6 +327,13 @@ MInstruction* WarpBuilder::buildNamedLambdaEnv(MDefinition* callee, | ||||||
|   MInstruction* namedLambda = MNewNamedLambdaObject::New(alloc(), templateObj); |   MInstruction* namedLambda = MNewNamedLambdaObject::New(alloc(), templateObj); | ||||||
|   current->add(namedLambda); |   current->add(namedLambda); | ||||||
| 
 | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  |   // Assert in debug mode we can elide the post write barriers.
 | ||||||
|  |   current->add(MAssertCanElidePostWriteBarrier::New(alloc(), namedLambda, env)); | ||||||
|  |   current->add( | ||||||
|  |       MAssertCanElidePostWriteBarrier::New(alloc(), namedLambda, callee)); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|   // Initialize the object's reserved slots. No post barrier is needed here:
 |   // Initialize the object's reserved slots. No post barrier is needed here:
 | ||||||
|   // the object will be allocated in the nursery if possible, and if the
 |   // the object will be allocated in the nursery if possible, and if the
 | ||||||
|   // tenured heap is used instead, a minor collection will have been performed
 |   // tenured heap is used instead, a minor collection will have been performed
 | ||||||
|  | @ -349,6 +356,12 @@ MInstruction* WarpBuilder::buildCallObject(MDefinition* callee, | ||||||
|   MNewCallObject* callObj = MNewCallObject::New(alloc(), templateCst); |   MNewCallObject* callObj = MNewCallObject::New(alloc(), templateCst); | ||||||
|   current->add(callObj); |   current->add(callObj); | ||||||
| 
 | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  |   // Assert in debug mode we can elide the post write barriers.
 | ||||||
|  |   current->add(MAssertCanElidePostWriteBarrier::New(alloc(), callObj, env)); | ||||||
|  |   current->add(MAssertCanElidePostWriteBarrier::New(alloc(), callObj, callee)); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|   // Initialize the object's reserved slots. No post barrier is needed here,
 |   // Initialize the object's reserved slots. No post barrier is needed here,
 | ||||||
|   // for the same reason as in buildNamedLambdaEnv.
 |   // for the same reason as in buildNamedLambdaEnv.
 | ||||||
|   size_t enclosingSlot = CallObject::enclosingEnvironmentSlot(); |   size_t enclosingSlot = CallObject::enclosingEnvironmentSlot(); | ||||||
|  | @ -379,6 +392,11 @@ MInstruction* WarpBuilder::buildCallObject(MDefinition* callee, | ||||||
|       param = current->getSlot(info().argSlotUnchecked(formal)); |       param = current->getSlot(info().argSlotUnchecked(formal)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  |     // Assert in debug mode we can elide the post write barrier.
 | ||||||
|  |     current->add(MAssertCanElidePostWriteBarrier::New(alloc(), callObj, param)); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|     if (slot >= numFixedSlots) { |     if (slot >= numFixedSlots) { | ||||||
|       if (!slots) { |       if (!slots) { | ||||||
|         slots = MSlots::New(alloc(), callObj); |         slots = MSlots::New(alloc(), callObj); | ||||||
|  | @ -1989,6 +2007,11 @@ bool WarpBuilder::build_PushLexicalEnv(BytecodeLocation loc) { | ||||||
|   auto* ins = MNewLexicalEnvironmentObject::New(alloc(), templateCst); |   auto* ins = MNewLexicalEnvironmentObject::New(alloc(), templateCst); | ||||||
|   current->add(ins); |   current->add(ins); | ||||||
| 
 | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  |   // Assert in debug mode we can elide the post write barrier.
 | ||||||
|  |   current->add(MAssertCanElidePostWriteBarrier::New(alloc(), ins, env)); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|   // Initialize the object's reserved slots. No post barrier is needed here,
 |   // Initialize the object's reserved slots. No post barrier is needed here,
 | ||||||
|   // for the same reason as in buildNamedLambdaEnv.
 |   // for the same reason as in buildNamedLambdaEnv.
 | ||||||
|   current->add(MStoreFixedSlot::NewUnbarriered( |   current->add(MStoreFixedSlot::NewUnbarriered( | ||||||
|  | @ -2010,6 +2033,11 @@ bool WarpBuilder::build_PushClassBodyEnv(BytecodeLocation loc) { | ||||||
|   auto* ins = MNewClassBodyEnvironmentObject::New(alloc(), templateCst); |   auto* ins = MNewClassBodyEnvironmentObject::New(alloc(), templateCst); | ||||||
|   current->add(ins); |   current->add(ins); | ||||||
| 
 | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  |   // Assert in debug mode we can elide the post write barrier.
 | ||||||
|  |   current->add(MAssertCanElidePostWriteBarrier::New(alloc(), ins, env)); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|   // Initialize the object's reserved slots. No post barrier is needed here,
 |   // Initialize the object's reserved slots. No post barrier is needed here,
 | ||||||
|   // for the same reason as in buildNamedLambdaEnv.
 |   // for the same reason as in buildNamedLambdaEnv.
 | ||||||
|   current->add(MStoreFixedSlot::NewUnbarriered( |   current->add(MStoreFixedSlot::NewUnbarriered( | ||||||
|  | @ -2045,6 +2073,12 @@ bool WarpBuilder::build_FreshenLexicalEnv(BytecodeLocation loc) { | ||||||
|   auto* ins = MNewLexicalEnvironmentObject::New(alloc(), templateCst); |   auto* ins = MNewLexicalEnvironmentObject::New(alloc(), templateCst); | ||||||
|   current->add(ins); |   current->add(ins); | ||||||
| 
 | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  |   // Assert in debug mode we can elide the post write barrier.
 | ||||||
|  |   current->add( | ||||||
|  |       MAssertCanElidePostWriteBarrier::New(alloc(), ins, enclosingEnv)); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|   // Initialize the object's reserved slots. No post barrier is needed here,
 |   // Initialize the object's reserved slots. No post barrier is needed here,
 | ||||||
|   // for the same reason as in buildNamedLambdaEnv.
 |   // for the same reason as in buildNamedLambdaEnv.
 | ||||||
|   current->add(MStoreFixedSlot::NewUnbarriered( |   current->add(MStoreFixedSlot::NewUnbarriered( | ||||||
|  | @ -2082,12 +2116,22 @@ bool WarpBuilder::build_FreshenLexicalEnv(BytecodeLocation loc) { | ||||||
|       auto* load = MLoadDynamicSlot::New(alloc(), envSlots, dynamicSlot); |       auto* load = MLoadDynamicSlot::New(alloc(), envSlots, dynamicSlot); | ||||||
|       current->add(load); |       current->add(load); | ||||||
| 
 | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  |       // Assert in debug mode we can elide the post write barrier.
 | ||||||
|  |       current->add(MAssertCanElidePostWriteBarrier::New(alloc(), ins, load)); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|       current->add( |       current->add( | ||||||
|           MStoreDynamicSlot::NewUnbarriered(alloc(), slots, dynamicSlot, load)); |           MStoreDynamicSlot::NewUnbarriered(alloc(), slots, dynamicSlot, load)); | ||||||
|     } else { |     } else { | ||||||
|       auto* load = MLoadFixedSlot::New(alloc(), env, slot); |       auto* load = MLoadFixedSlot::New(alloc(), env, slot); | ||||||
|       current->add(load); |       current->add(load); | ||||||
| 
 | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  |       // Assert in debug mode we can elide the post write barrier.
 | ||||||
|  |       current->add(MAssertCanElidePostWriteBarrier::New(alloc(), ins, load)); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|       current->add(MStoreFixedSlot::NewUnbarriered(alloc(), ins, slot, load)); |       current->add(MStoreFixedSlot::NewUnbarriered(alloc(), ins, slot, load)); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | @ -2108,6 +2152,12 @@ bool WarpBuilder::build_RecreateLexicalEnv(BytecodeLocation loc) { | ||||||
|   auto* ins = MNewLexicalEnvironmentObject::New(alloc(), templateCst); |   auto* ins = MNewLexicalEnvironmentObject::New(alloc(), templateCst); | ||||||
|   current->add(ins); |   current->add(ins); | ||||||
| 
 | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  |   // Assert in debug mode we can elide the post write barrier.
 | ||||||
|  |   current->add( | ||||||
|  |       MAssertCanElidePostWriteBarrier::New(alloc(), ins, enclosingEnv)); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|   // Initialize the object's reserved slots. No post barrier is needed here,
 |   // Initialize the object's reserved slots. No post barrier is needed here,
 | ||||||
|   // for the same reason as in buildNamedLambdaEnv.
 |   // for the same reason as in buildNamedLambdaEnv.
 | ||||||
|   current->add(MStoreFixedSlot::NewUnbarriered( |   current->add(MStoreFixedSlot::NewUnbarriered( | ||||||
|  | @ -2130,6 +2180,11 @@ bool WarpBuilder::build_PushVarEnv(BytecodeLocation loc) { | ||||||
|   auto* ins = MNewVarEnvironmentObject::New(alloc(), templateCst); |   auto* ins = MNewVarEnvironmentObject::New(alloc(), templateCst); | ||||||
|   current->add(ins); |   current->add(ins); | ||||||
| 
 | 
 | ||||||
|  | #ifdef DEBUG | ||||||
|  |   // Assert in debug mode we can elide the post write barrier.
 | ||||||
|  |   current->add(MAssertCanElidePostWriteBarrier::New(alloc(), ins, env)); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|   // Initialize the object's reserved slots. No post barrier is needed here,
 |   // Initialize the object's reserved slots. No post barrier is needed here,
 | ||||||
|   // for the same reason as in buildNamedLambdaEnv.
 |   // for the same reason as in buildNamedLambdaEnv.
 | ||||||
|   current->add(MStoreFixedSlot::NewUnbarriered( |   current->add(MStoreFixedSlot::NewUnbarriered( | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 André Bargull
						André Bargull