| Index: src/ia32/codegen-ia32.cc
 | 
| ===================================================================
 | 
| --- src/ia32/codegen-ia32.cc	(revision 4703)
 | 
| +++ src/ia32/codegen-ia32.cc	(working copy)
 | 
| @@ -4198,6 +4198,7 @@
 | 
|    frame_->EmitPush(eax);  // <- slot 3
 | 
|    frame_->EmitPush(edx);  // <- slot 2
 | 
|    __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset));
 | 
| +  __ SmiTag(eax);
 | 
|    frame_->EmitPush(eax);  // <- slot 1
 | 
|    frame_->EmitPush(Immediate(Smi::FromInt(0)));  // <- slot 0
 | 
|    entry.Jump();
 | 
| @@ -4209,6 +4210,7 @@
 | 
|  
 | 
|    // Push the length of the array and the initial index onto the stack.
 | 
|    __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
 | 
| +  __ SmiTag(eax);
 | 
|    frame_->EmitPush(eax);  // <- slot 1
 | 
|    frame_->EmitPush(Immediate(Smi::FromInt(0)));  // <- slot 0
 | 
|  
 | 
| @@ -6598,9 +6600,9 @@
 | 
|      __ mov(FieldOperand(ebx, HeapObject::kMapOffset),
 | 
|             Immediate(Factory::fixed_array_map()));
 | 
|      // Set length.
 | 
| +    __ SmiUntag(ecx);
 | 
|      __ mov(FieldOperand(ebx, FixedArray::kLengthOffset), ecx);
 | 
|      // Fill contents of fixed-array with the-hole.
 | 
| -    __ SmiUntag(ecx);
 | 
|      __ mov(edx, Immediate(Factory::the_hole_value()));
 | 
|      __ lea(ebx, FieldOperand(ebx, FixedArray::kHeaderSize));
 | 
|      // Fill fixed array elements with hole.
 | 
| @@ -6704,6 +6706,7 @@
 | 
|  
 | 
|    // Check if we could add new entry to cache.
 | 
|    __ mov(ebx, FieldOperand(ecx, FixedArray::kLengthOffset));
 | 
| +  __ SmiTag(ebx);
 | 
|    __ cmp(ebx, FieldOperand(ecx, JSFunctionResultCache::kCacheSizeOffset));
 | 
|    __ j(greater, &add_new_entry);
 | 
|  
 | 
| @@ -6901,8 +6904,12 @@
 | 
|    // (or them and test against Smi mask.)
 | 
|  
 | 
|    __ mov(tmp2.reg(), tmp1.reg());
 | 
| -  __ RecordWriteHelper(tmp2.reg(), index1.reg(), object.reg());
 | 
| -  __ RecordWriteHelper(tmp1.reg(), index2.reg(), object.reg());
 | 
| +  RecordWriteStub recordWrite1(tmp2.reg(), index1.reg(), object.reg());
 | 
| +  __ CallStub(&recordWrite1);
 | 
| +
 | 
| +  RecordWriteStub recordWrite2(tmp1.reg(), index2.reg(), object.reg());
 | 
| +  __ CallStub(&recordWrite2);
 | 
| +
 | 
|    __ bind(&done);
 | 
|  
 | 
|    deferred->BindExit();
 | 
| @@ -8601,10 +8608,13 @@
 | 
|      Result elements = allocator()->Allocate();
 | 
|      ASSERT(elements.is_valid());
 | 
|  
 | 
| -    result = elements;
 | 
| +    // Use a fresh temporary for the index and later the loaded
 | 
| +    // value.
 | 
| +    result = allocator()->Allocate();
 | 
| +    ASSERT(result.is_valid());
 | 
|  
 | 
|      DeferredReferenceGetKeyedValue* deferred =
 | 
| -        new DeferredReferenceGetKeyedValue(elements.reg(),
 | 
| +        new DeferredReferenceGetKeyedValue(result.reg(),
 | 
|                                             receiver.reg(),
 | 
|                                             key.reg());
 | 
|  
 | 
| @@ -8636,17 +8646,20 @@
 | 
|             Immediate(Factory::fixed_array_map()));
 | 
|      deferred->Branch(not_equal);
 | 
|  
 | 
| -    // Check that the key is within bounds.
 | 
| -    __ cmp(key.reg(),
 | 
| +    // Shift the key to get the actual index value and check that
 | 
| +    // it is within bounds. Use unsigned comparison to handle negative keys.
 | 
| +    __ mov(result.reg(), key.reg());
 | 
| +    __ SmiUntag(result.reg());
 | 
| +    __ cmp(result.reg(),
 | 
|             FieldOperand(elements.reg(), FixedArray::kLengthOffset));
 | 
|      deferred->Branch(above_equal);
 | 
|  
 | 
|      // Load and check that the result is not the hole.
 | 
| -    ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
 | 
|      __ mov(result.reg(), Operand(elements.reg(),
 | 
| -                                 key.reg(),
 | 
| -                                 times_2,
 | 
| +                                 result.reg(),
 | 
| +                                 times_4,
 | 
|                                   FixedArray::kHeaderSize - kHeapObjectTag));
 | 
| +    elements.Unuse();
 | 
|      __ cmp(Operand(result.reg()), Immediate(Factory::the_hole_value()));
 | 
|      deferred->Branch(equal);
 | 
|      __ IncrementCounter(&Counters::keyed_load_inline, 1);
 | 
| @@ -8731,7 +8744,7 @@
 | 
|  
 | 
|      // Check whether it is possible to omit the write barrier. If the elements
 | 
|      // array is in new space or the value written is a smi we can safely update
 | 
| -    // the elements array without write barrier.
 | 
| +    // the elements array without updating the remembered set.
 | 
|      Label in_new_space;
 | 
|      __ InNewSpace(tmp.reg(), tmp2.reg(), equal, &in_new_space);
 | 
|      if (!value_is_constant) {
 | 
| @@ -9001,8 +9014,7 @@
 | 
|  
 | 
|    // Setup the object header.
 | 
|    __ mov(FieldOperand(eax, HeapObject::kMapOffset), Factory::context_map());
 | 
| -  __ mov(FieldOperand(eax, Context::kLengthOffset),
 | 
| -         Immediate(Smi::FromInt(length)));
 | 
| +  __ mov(FieldOperand(eax, Array::kLengthOffset), Immediate(length));
 | 
|  
 | 
|    // Setup the fixed slots.
 | 
|    __ xor_(ebx, Operand(ebx));  // Set to NULL.
 | 
| @@ -10965,8 +10977,9 @@
 | 
|    __ test(ecx, Operand(ecx));
 | 
|    __ j(zero, &done);
 | 
|  
 | 
| -  // Get the parameters pointer from the stack.
 | 
| +  // Get the parameters pointer from the stack and untag the length.
 | 
|    __ mov(edx, Operand(esp, 2 * kPointerSize));
 | 
| +  __ SmiUntag(ecx);
 | 
|  
 | 
|    // Setup the elements pointer in the allocated arguments object and
 | 
|    // initialize the header in the elements fixed array.
 | 
| @@ -10975,8 +10988,6 @@
 | 
|    __ mov(FieldOperand(edi, FixedArray::kMapOffset),
 | 
|           Immediate(Factory::fixed_array_map()));
 | 
|    __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx);
 | 
| -  // Untag the length for the loop below.
 | 
| -  __ SmiUntag(ecx);
 | 
|  
 | 
|    // Copy the fixed array slots.
 | 
|    Label loop;
 | 
| @@ -11105,7 +11116,6 @@
 | 
|    // Check that the last match info has space for the capture registers and the
 | 
|    // additional information.
 | 
|    __ mov(eax, FieldOperand(ebx, FixedArray::kLengthOffset));
 | 
| -  __ SmiUntag(eax);
 | 
|    __ add(Operand(edx), Immediate(RegExpImpl::kLastMatchOverhead));
 | 
|    __ cmp(edx, Operand(eax));
 | 
|    __ j(greater, &runtime);
 | 
| @@ -11349,7 +11359,7 @@
 | 
|    // Make the hash mask from the length of the number string cache. It
 | 
|    // contains two elements (number and string) for each cache entry.
 | 
|    __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
 | 
| -  __ shr(mask, kSmiTagSize + 1);  // Untag length and divide it by two.
 | 
| +  __ shr(mask, 1);  // Divide length by two (length is not a smi).
 | 
|    __ sub(Operand(mask), Immediate(1));  // Make mask.
 | 
|  
 | 
|    // Calculate the entry in the number string cache. The hash value in the
 | 
| @@ -11440,6 +11450,12 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void RecordWriteStub::Generate(MacroAssembler* masm) {
 | 
| +  masm->RecordWriteHelper(object_, addr_, scratch_);
 | 
| +  masm->ret(0);
 | 
| +}
 | 
| +
 | 
| +
 | 
|  static int NegativeComparisonResult(Condition cc) {
 | 
|    ASSERT(cc != equal);
 | 
|    ASSERT((cc == less) || (cc == less_equal)
 | 
| 
 |