Chromium Code Reviews| Index: src/arm/codegen-arm.cc |
| =================================================================== |
| --- src/arm/codegen-arm.cc (revision 4996) |
| +++ src/arm/codegen-arm.cc (working copy) |
| @@ -1745,11 +1745,15 @@ |
| val = node->fun(); // NULL if we don't have a function |
| } |
| + |
| if (val != NULL) { |
| + WriteBarrierCharacter wb_info = |
| + val->type()->IsLikelySmi() ? LIKELY_SMI : UNLIKELY_SMI; |
| + if (val->AsLiteral() != NULL) wb_info = NEVER_NEWSPACE; |
| // Set initial value. |
| Reference target(this, node->proxy()); |
| Load(val); |
| - target.SetValue(NOT_CONST_INIT); |
| + target.SetValue(NOT_CONST_INIT, wb_info); |
| // Get rid of the assigned value (declarations are statements). |
| frame_->Drop(); |
| @@ -2485,13 +2489,13 @@ |
| if (each.size() > 0) { |
| __ ldr(r0, frame_->ElementAt(each.size())); |
| frame_->EmitPush(r0); |
| - each.SetValue(NOT_CONST_INIT); |
| + each.SetValue(NOT_CONST_INIT, UNLIKELY_SMI); |
| frame_->Drop(2); |
| } else { |
| // If the reference was to a slot we rely on the convenient property |
| // that it doesn't matter whether a value (eg, r3 pushed above) is |
| // right on top of or right underneath a zero-sized reference. |
| - each.SetValue(NOT_CONST_INIT); |
| + each.SetValue(NOT_CONST_INIT, UNLIKELY_SMI); |
| frame_->Drop(); |
| } |
| } |
| @@ -3646,6 +3650,8 @@ |
| // Evaluate the receiver subexpression. |
| Load(prop->obj()); |
| + WriteBarrierCharacter wb_info; |
| + |
| // Change to slow case in the beginning of an initialization block to |
| // avoid the quadratic behavior of repeatedly adding fast properties. |
| if (node->starts_initialization_block()) { |
| @@ -3667,7 +3673,7 @@ |
| // [tos] : key |
| // [tos+1] : receiver |
| // [tos+2] : receiver if at the end of an initialization block |
| - |
| + // |
| // Evaluate the right-hand side. |
| if (node->is_compound()) { |
| // For a compound assignment the right-hand side is a binary operation |
| @@ -3699,9 +3705,13 @@ |
| overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE, |
| inline_smi); |
| } |
| + wb_info = node->type()->IsLikelySmi() ? LIKELY_SMI : UNLIKELY_SMI; |
| } else { |
| // For non-compound assignment just load the right-hand side. |
| Load(node->value()); |
| + wb_info = node->value()->AsLiteral() != NULL ? |
| + NEVER_NEWSPACE : |
| + (node->value()->type()->IsLikelySmi() ? LIKELY_SMI : UNLIKELY_SMI); |
| } |
| // Stack layout: |
| @@ -3713,7 +3723,7 @@ |
| // Perform the assignment. It is safe to ignore constants here. |
| ASSERT(node->op() != Token::INIT_CONST); |
| CodeForSourcePosition(node->position()); |
| - EmitKeyedStore(prop->key()->type()); |
| + EmitKeyedStore(prop->key()->type(), wb_info); |
| frame_->EmitPush(r0); |
| // Stack layout: |
| @@ -5509,7 +5519,7 @@ |
| __ sub(value, value, Operand(Smi::FromInt(1))); |
| } |
| frame_->EmitPush(value); |
| - target.SetValue(NOT_CONST_INIT); |
| + target.SetValue(NOT_CONST_INIT, LIKELY_SMI); |
| if (is_postfix) frame_->Pop(); |
| ASSERT_EQ(original_height + 1, frame_->height()); |
| return; |
| @@ -5608,7 +5618,7 @@ |
| // Set the target with the result, leaving the result on |
| // top of the stack. Removes the target from the stack if |
| // it has a non-zero size. |
| - if (!is_const) target.SetValue(NOT_CONST_INIT); |
| + if (!is_const) target.SetValue(NOT_CONST_INIT, LIKELY_SMI); |
| } |
| // Postfix: Discard the new value and use the old. |
| @@ -6341,7 +6351,8 @@ |
| } |
| -void CodeGenerator::EmitKeyedStore(StaticType* key_type) { |
| +void CodeGenerator::EmitKeyedStore(StaticType* key_type, |
| + WriteBarrierCharacter wb_info) { |
| // Generate inlined version of the keyed store if the code is in a loop |
| // and the key is likely to be a smi. |
| if (loop_nesting() > 0 && key_type->IsLikelySmi()) { |
| @@ -6357,25 +6368,45 @@ |
| __ IncrementCounter(&Counters::keyed_store_inline, 1, |
| scratch1, scratch2); |
| + |
| + |
| // Load the value, key and receiver from the stack. |
| + bool value_is_harmless = frame_->KnownSmiAt(0); |
| + if (wb_info == NEVER_NEWSPACE) value_is_harmless = true; |
| + bool key_is_smi = frame_->KnownSmiAt(1); |
| Register value = frame_->PopToRegister(); |
| Register key = frame_->PopToRegister(value); |
| VirtualFrame::SpilledScope spilled(frame_); |
| Register receiver = r2; |
| frame_->EmitPop(receiver); |
| +#ifdef DEBUG |
| + bool we_remembered_the_write_barrier = value_is_harmless; |
| +#endif |
| + |
| // The deferred code expects value, key and receiver in registers. |
| DeferredReferenceSetKeyedValue* deferred = |
| new DeferredReferenceSetKeyedValue(value, key, receiver); |
| // Check that the value is a smi. As this inlined code does not set the |
| // write barrier it is only possible to store smi values. |
| - __ tst(value, Operand(kSmiTagMask)); |
| - deferred->Branch(ne); |
| + if (!value_is_harmless) { |
| + // If the value is not likely to be a Smi then lets test the fixed array |
|
William Hesse
2010/07/01 15:00:59
let's
|
| + // for new space instead. See below. |
| + if (wb_info == LIKELY_SMI) { |
| + __ tst(value, Operand(kSmiTagMask)); |
| + deferred->Branch(ne); |
| +#ifdef DEBUG |
| + we_remembered_the_write_barrier = true; |
| +#endif |
| + } |
| + } |
| - // Check that the key is a smi. |
| - __ tst(key, Operand(kSmiTagMask)); |
| - deferred->Branch(ne); |
| + if (!key_is_smi) { |
| + // Check that the key is a smi. |
| + __ tst(key, Operand(kSmiTagMask)); |
| + deferred->Branch(ne); |
| + } |
| // Check that the receiver is a heap object. |
| __ tst(receiver, Operand(kSmiTagMask)); |
| @@ -6391,24 +6422,35 @@ |
| __ cmp(scratch1, key); |
| deferred->Branch(ls); // Unsigned less equal. |
| + // Get the elements array from the receiver and check that it |
| + // is not a dictionary. |
|
William Hesse
2010/07/01 15:00:59
The check that it is a dictionary is pretty far aw
|
| + __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| + if (!value_is_harmless && wb_info != LIKELY_SMI) { |
| + Label ok; |
| + __ and_(scratch2, scratch1, Operand(ExternalReference::new_space_mask())); |
| + __ cmp(scratch2, Operand(ExternalReference::new_space_start())); |
| + __ tst(value, Operand(kSmiTagMask), ne); |
| + deferred->Branch(ne); |
| +#ifdef DEBUG |
| + we_remembered_the_write_barrier = true; |
| +#endif |
| + } |
| + __ ldr(scratch2, FieldMemOperand(scratch1, JSObject::kMapOffset)); |
| // The following instructions are the part of the inlined store keyed |
| // property code which can be patched. Therefore the exact number of |
| // instructions generated need to be fixed, so the constant pool is blocked |
| // while generating this code. |
| { Assembler::BlockConstPoolScope block_const_pool(masm_); |
| - // Get the elements array from the receiver and check that it |
| - // is not a dictionary. |
| - __ ldr(scratch1, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| - __ ldr(scratch2, FieldMemOperand(scratch1, JSObject::kMapOffset)); |
| +#ifdef DEBUG |
| + Label check_inlined_codesize; |
| + masm_->bind(&check_inlined_codesize); |
| +#endif |
| + |
| // Read the fixed array map from the constant pool (not from the root |
| // array) so that the value can be patched. When debugging, we patch this |
| // comparison to always fail so that we will hit the IC call in the |
| // deferred code which will allow the debugger to break for fast case |
| // stores. |
| -#ifdef DEBUG |
| - Label check_inlined_codesize; |
| - masm_->bind(&check_inlined_codesize); |
| -#endif |
| __ mov(scratch3, Operand(Factory::fixed_array_map())); |
| __ cmp(scratch2, scratch3); |
| deferred->Branch(ne); |
| @@ -6425,6 +6467,8 @@ |
| masm_->InstructionsGeneratedSince(&check_inlined_codesize)); |
| } |
| + ASSERT(we_remembered_the_write_barrier); |
| + |
| deferred->BindExit(); |
| } else { |
| frame()->CallKeyedStoreIC(); |
| @@ -6522,7 +6566,7 @@ |
| } |
| -void Reference::SetValue(InitState init_state) { |
| +void Reference::SetValue(InitState init_state, WriteBarrierCharacter wb_info) { |
| ASSERT(!is_illegal()); |
| ASSERT(!cgen_->has_cc()); |
| MacroAssembler* masm = cgen_->masm(); |
| @@ -6554,7 +6598,7 @@ |
| Property* property = expression_->AsProperty(); |
| ASSERT(property != NULL); |
| cgen_->CodeForSourcePosition(property->position()); |
| - cgen_->EmitKeyedStore(property->key()->type()); |
| + cgen_->EmitKeyedStore(property->key()->type(), wb_info); |
| frame->EmitPush(r0); |
| set_unloaded(); |
| break; |