| OLD | NEW | 
|     1 // Copyright 2012 the V8 project authors. All rights reserved. |     1 // Copyright 2012 the V8 project authors. All rights reserved. | 
|     2 // Use of this source code is governed by a BSD-style license that can be |     2 // Use of this source code is governed by a BSD-style license that can be | 
|     3 // found in the LICENSE file. |     3 // found in the LICENSE file. | 
|     4  |     4  | 
|     5 #include "src/v8.h" |     5 #include "src/v8.h" | 
|     6  |     6  | 
|     7 #if V8_TARGET_ARCH_IA32 |     7 #if V8_TARGET_ARCH_IA32 | 
|     8  |     8  | 
|     9 #include "src/bootstrapper.h" |     9 #include "src/bootstrapper.h" | 
|    10 #include "src/codegen.h" |    10 #include "src/codegen.h" | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
|    26       has_frame_(false) { |    26       has_frame_(false) { | 
|    27   if (isolate() != NULL) { |    27   if (isolate() != NULL) { | 
|    28     // TODO(titzer): should we just use a null handle here instead? |    28     // TODO(titzer): should we just use a null handle here instead? | 
|    29     code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), |    29     code_object_ = Handle<Object>(isolate()->heap()->undefined_value(), | 
|    30                                   isolate()); |    30                                   isolate()); | 
|    31   } |    31   } | 
|    32 } |    32 } | 
|    33  |    33  | 
|    34  |    34  | 
|    35 void MacroAssembler::Load(Register dst, const Operand& src, Representation r) { |    35 void MacroAssembler::Load(Register dst, const Operand& src, Representation r) { | 
|    36   ASSERT(!r.IsDouble()); |    36   DCHECK(!r.IsDouble()); | 
|    37   if (r.IsInteger8()) { |    37   if (r.IsInteger8()) { | 
|    38     movsx_b(dst, src); |    38     movsx_b(dst, src); | 
|    39   } else if (r.IsUInteger8()) { |    39   } else if (r.IsUInteger8()) { | 
|    40     movzx_b(dst, src); |    40     movzx_b(dst, src); | 
|    41   } else if (r.IsInteger16()) { |    41   } else if (r.IsInteger16()) { | 
|    42     movsx_w(dst, src); |    42     movsx_w(dst, src); | 
|    43   } else if (r.IsUInteger16()) { |    43   } else if (r.IsUInteger16()) { | 
|    44     movzx_w(dst, src); |    44     movzx_w(dst, src); | 
|    45   } else { |    45   } else { | 
|    46     mov(dst, src); |    46     mov(dst, src); | 
|    47   } |    47   } | 
|    48 } |    48 } | 
|    49  |    49  | 
|    50  |    50  | 
|    51 void MacroAssembler::Store(Register src, const Operand& dst, Representation r) { |    51 void MacroAssembler::Store(Register src, const Operand& dst, Representation r) { | 
|    52   ASSERT(!r.IsDouble()); |    52   DCHECK(!r.IsDouble()); | 
|    53   if (r.IsInteger8() || r.IsUInteger8()) { |    53   if (r.IsInteger8() || r.IsUInteger8()) { | 
|    54     mov_b(dst, src); |    54     mov_b(dst, src); | 
|    55   } else if (r.IsInteger16() || r.IsUInteger16()) { |    55   } else if (r.IsInteger16() || r.IsUInteger16()) { | 
|    56     mov_w(dst, src); |    56     mov_w(dst, src); | 
|    57   } else { |    57   } else { | 
|    58     if (r.IsHeapObject()) { |    58     if (r.IsHeapObject()) { | 
|    59       AssertNotSmi(src); |    59       AssertNotSmi(src); | 
|    60     } else if (r.IsSmi()) { |    60     } else if (r.IsSmi()) { | 
|    61       AssertSmi(src); |    61       AssertSmi(src); | 
|    62     } |    62     } | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|    76   mov(destination, Immediate(index)); |    76   mov(destination, Immediate(index)); | 
|    77   mov(destination, Operand::StaticArray(destination, |    77   mov(destination, Operand::StaticArray(destination, | 
|    78                                         times_pointer_size, |    78                                         times_pointer_size, | 
|    79                                         roots_array_start)); |    79                                         roots_array_start)); | 
|    80 } |    80 } | 
|    81  |    81  | 
|    82  |    82  | 
|    83 void MacroAssembler::StoreRoot(Register source, |    83 void MacroAssembler::StoreRoot(Register source, | 
|    84                                Register scratch, |    84                                Register scratch, | 
|    85                                Heap::RootListIndex index) { |    85                                Heap::RootListIndex index) { | 
|    86   ASSERT(Heap::RootCanBeWrittenAfterInitialization(index)); |    86   DCHECK(Heap::RootCanBeWrittenAfterInitialization(index)); | 
|    87   ExternalReference roots_array_start = |    87   ExternalReference roots_array_start = | 
|    88       ExternalReference::roots_array_start(isolate()); |    88       ExternalReference::roots_array_start(isolate()); | 
|    89   mov(scratch, Immediate(index)); |    89   mov(scratch, Immediate(index)); | 
|    90   mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), |    90   mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), | 
|    91       source); |    91       source); | 
|    92 } |    92 } | 
|    93  |    93  | 
|    94  |    94  | 
|    95 void MacroAssembler::CompareRoot(Register with, |    95 void MacroAssembler::CompareRoot(Register with, | 
|    96                                  Register scratch, |    96                                  Register scratch, | 
|    97                                  Heap::RootListIndex index) { |    97                                  Heap::RootListIndex index) { | 
|    98   ExternalReference roots_array_start = |    98   ExternalReference roots_array_start = | 
|    99       ExternalReference::roots_array_start(isolate()); |    99       ExternalReference::roots_array_start(isolate()); | 
|   100   mov(scratch, Immediate(index)); |   100   mov(scratch, Immediate(index)); | 
|   101   cmp(with, Operand::StaticArray(scratch, |   101   cmp(with, Operand::StaticArray(scratch, | 
|   102                                 times_pointer_size, |   102                                 times_pointer_size, | 
|   103                                 roots_array_start)); |   103                                 roots_array_start)); | 
|   104 } |   104 } | 
|   105  |   105  | 
|   106  |   106  | 
|   107 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { |   107 void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { | 
|   108   ASSERT(isolate()->heap()->RootCanBeTreatedAsConstant(index)); |   108   DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index)); | 
|   109   Handle<Object> value(&isolate()->heap()->roots_array_start()[index]); |   109   Handle<Object> value(&isolate()->heap()->roots_array_start()[index]); | 
|   110   cmp(with, value); |   110   cmp(with, value); | 
|   111 } |   111 } | 
|   112  |   112  | 
|   113  |   113  | 
|   114 void MacroAssembler::CompareRoot(const Operand& with, |   114 void MacroAssembler::CompareRoot(const Operand& with, | 
|   115                                  Heap::RootListIndex index) { |   115                                  Heap::RootListIndex index) { | 
|   116   ASSERT(isolate()->heap()->RootCanBeTreatedAsConstant(index)); |   116   DCHECK(isolate()->heap()->RootCanBeTreatedAsConstant(index)); | 
|   117   Handle<Object> value(&isolate()->heap()->roots_array_start()[index]); |   117   Handle<Object> value(&isolate()->heap()->roots_array_start()[index]); | 
|   118   cmp(with, value); |   118   cmp(with, value); | 
|   119 } |   119 } | 
|   120  |   120  | 
|   121  |   121  | 
|   122 void MacroAssembler::InNewSpace( |   122 void MacroAssembler::InNewSpace( | 
|   123     Register object, |   123     Register object, | 
|   124     Register scratch, |   124     Register scratch, | 
|   125     Condition cc, |   125     Condition cc, | 
|   126     Label* condition_met, |   126     Label* condition_met, | 
|   127     Label::Distance condition_met_distance) { |   127     Label::Distance condition_met_distance) { | 
|   128   ASSERT(cc == equal || cc == not_equal); |   128   DCHECK(cc == equal || cc == not_equal); | 
|   129   if (scratch.is(object)) { |   129   if (scratch.is(object)) { | 
|   130     and_(scratch, Immediate(~Page::kPageAlignmentMask)); |   130     and_(scratch, Immediate(~Page::kPageAlignmentMask)); | 
|   131   } else { |   131   } else { | 
|   132     mov(scratch, Immediate(~Page::kPageAlignmentMask)); |   132     mov(scratch, Immediate(~Page::kPageAlignmentMask)); | 
|   133     and_(scratch, object); |   133     and_(scratch, object); | 
|   134   } |   134   } | 
|   135   // Check that we can use a test_b. |   135   // Check that we can use a test_b. | 
|   136   ASSERT(MemoryChunk::IN_FROM_SPACE < 8); |   136   DCHECK(MemoryChunk::IN_FROM_SPACE < 8); | 
|   137   ASSERT(MemoryChunk::IN_TO_SPACE < 8); |   137   DCHECK(MemoryChunk::IN_TO_SPACE < 8); | 
|   138   int mask = (1 << MemoryChunk::IN_FROM_SPACE) |   138   int mask = (1 << MemoryChunk::IN_FROM_SPACE) | 
|   139            | (1 << MemoryChunk::IN_TO_SPACE); |   139            | (1 << MemoryChunk::IN_TO_SPACE); | 
|   140   // If non-zero, the page belongs to new-space. |   140   // If non-zero, the page belongs to new-space. | 
|   141   test_b(Operand(scratch, MemoryChunk::kFlagsOffset), |   141   test_b(Operand(scratch, MemoryChunk::kFlagsOffset), | 
|   142          static_cast<uint8_t>(mask)); |   142          static_cast<uint8_t>(mask)); | 
|   143   j(cc, condition_met, condition_met_distance); |   143   j(cc, condition_met, condition_met_distance); | 
|   144 } |   144 } | 
|   145  |   145  | 
|   146  |   146  | 
|   147 void MacroAssembler::RememberedSetHelper( |   147 void MacroAssembler::RememberedSetHelper( | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
|   169   mov(Operand::StaticVariable(store_buffer), scratch); |   169   mov(Operand::StaticVariable(store_buffer), scratch); | 
|   170   // Call stub on end of buffer. |   170   // Call stub on end of buffer. | 
|   171   // Check for end of buffer. |   171   // Check for end of buffer. | 
|   172   test(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit)); |   172   test(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit)); | 
|   173   if (and_then == kReturnAtEnd) { |   173   if (and_then == kReturnAtEnd) { | 
|   174     Label buffer_overflowed; |   174     Label buffer_overflowed; | 
|   175     j(not_equal, &buffer_overflowed, Label::kNear); |   175     j(not_equal, &buffer_overflowed, Label::kNear); | 
|   176     ret(0); |   176     ret(0); | 
|   177     bind(&buffer_overflowed); |   177     bind(&buffer_overflowed); | 
|   178   } else { |   178   } else { | 
|   179     ASSERT(and_then == kFallThroughAtEnd); |   179     DCHECK(and_then == kFallThroughAtEnd); | 
|   180     j(equal, &done, Label::kNear); |   180     j(equal, &done, Label::kNear); | 
|   181   } |   181   } | 
|   182   StoreBufferOverflowStub store_buffer_overflow = |   182   StoreBufferOverflowStub store_buffer_overflow = | 
|   183       StoreBufferOverflowStub(isolate(), save_fp); |   183       StoreBufferOverflowStub(isolate(), save_fp); | 
|   184   CallStub(&store_buffer_overflow); |   184   CallStub(&store_buffer_overflow); | 
|   185   if (and_then == kReturnAtEnd) { |   185   if (and_then == kReturnAtEnd) { | 
|   186     ret(0); |   186     ret(0); | 
|   187   } else { |   187   } else { | 
|   188     ASSERT(and_then == kFallThroughAtEnd); |   188     DCHECK(and_then == kFallThroughAtEnd); | 
|   189     bind(&done); |   189     bind(&done); | 
|   190   } |   190   } | 
|   191 } |   191 } | 
|   192  |   192  | 
|   193  |   193  | 
|   194 void MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg, |   194 void MacroAssembler::ClampDoubleToUint8(XMMRegister input_reg, | 
|   195                                         XMMRegister scratch_reg, |   195                                         XMMRegister scratch_reg, | 
|   196                                         Register result_reg) { |   196                                         Register result_reg) { | 
|   197   Label done; |   197   Label done; | 
|   198   Label conv_failure; |   198   Label conv_failure; | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   248   bind(&done); |   248   bind(&done); | 
|   249 } |   249 } | 
|   250  |   250  | 
|   251  |   251  | 
|   252 void MacroAssembler::DoubleToI(Register result_reg, |   252 void MacroAssembler::DoubleToI(Register result_reg, | 
|   253                                XMMRegister input_reg, |   253                                XMMRegister input_reg, | 
|   254                                XMMRegister scratch, |   254                                XMMRegister scratch, | 
|   255                                MinusZeroMode minus_zero_mode, |   255                                MinusZeroMode minus_zero_mode, | 
|   256                                Label* conversion_failed, |   256                                Label* conversion_failed, | 
|   257                                Label::Distance dst) { |   257                                Label::Distance dst) { | 
|   258   ASSERT(!input_reg.is(scratch)); |   258   DCHECK(!input_reg.is(scratch)); | 
|   259   cvttsd2si(result_reg, Operand(input_reg)); |   259   cvttsd2si(result_reg, Operand(input_reg)); | 
|   260   Cvtsi2sd(scratch, Operand(result_reg)); |   260   Cvtsi2sd(scratch, Operand(result_reg)); | 
|   261   ucomisd(scratch, input_reg); |   261   ucomisd(scratch, input_reg); | 
|   262   j(not_equal, conversion_failed, dst); |   262   j(not_equal, conversion_failed, dst); | 
|   263   j(parity_even, conversion_failed, dst);  // NaN. |   263   j(parity_even, conversion_failed, dst);  // NaN. | 
|   264   if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { |   264   if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { | 
|   265     Label done; |   265     Label done; | 
|   266     // The integer converted back is equal to the original. We |   266     // The integer converted back is equal to the original. We | 
|   267     // only have to test if we got -0 as an input. |   267     // only have to test if we got -0 as an input. | 
|   268     test(result_reg, Operand(result_reg)); |   268     test(result_reg, Operand(result_reg)); | 
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   344   bind(&done); |   344   bind(&done); | 
|   345 } |   345 } | 
|   346  |   346  | 
|   347  |   347  | 
|   348 void MacroAssembler::TaggedToI(Register result_reg, |   348 void MacroAssembler::TaggedToI(Register result_reg, | 
|   349                                Register input_reg, |   349                                Register input_reg, | 
|   350                                XMMRegister temp, |   350                                XMMRegister temp, | 
|   351                                MinusZeroMode minus_zero_mode, |   351                                MinusZeroMode minus_zero_mode, | 
|   352                                Label* lost_precision) { |   352                                Label* lost_precision) { | 
|   353   Label done; |   353   Label done; | 
|   354   ASSERT(!temp.is(xmm0)); |   354   DCHECK(!temp.is(xmm0)); | 
|   355  |   355  | 
|   356   cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |   356   cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 
|   357       isolate()->factory()->heap_number_map()); |   357       isolate()->factory()->heap_number_map()); | 
|   358   j(not_equal, lost_precision, Label::kNear); |   358   j(not_equal, lost_precision, Label::kNear); | 
|   359  |   359  | 
|   360   ASSERT(!temp.is(no_xmm_reg)); |   360   DCHECK(!temp.is(no_xmm_reg)); | 
|   361  |   361  | 
|   362   movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |   362   movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 
|   363   cvttsd2si(result_reg, Operand(xmm0)); |   363   cvttsd2si(result_reg, Operand(xmm0)); | 
|   364   Cvtsi2sd(temp, Operand(result_reg)); |   364   Cvtsi2sd(temp, Operand(result_reg)); | 
|   365   ucomisd(xmm0, temp); |   365   ucomisd(xmm0, temp); | 
|   366   RecordComment("Deferred TaggedToI: lost precision"); |   366   RecordComment("Deferred TaggedToI: lost precision"); | 
|   367   j(not_equal, lost_precision, Label::kNear); |   367   j(not_equal, lost_precision, Label::kNear); | 
|   368   RecordComment("Deferred TaggedToI: NaN"); |   368   RecordComment("Deferred TaggedToI: NaN"); | 
|   369   j(parity_even, lost_precision, Label::kNear); |   369   j(parity_even, lost_precision, Label::kNear); | 
|   370   if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { |   370   if (minus_zero_mode == FAIL_ON_MINUS_ZERO) { | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
|   399     SaveFPRegsMode save_fp, |   399     SaveFPRegsMode save_fp, | 
|   400     RememberedSetAction remembered_set_action, |   400     RememberedSetAction remembered_set_action, | 
|   401     SmiCheck smi_check, |   401     SmiCheck smi_check, | 
|   402     PointersToHereCheck pointers_to_here_check_for_value) { |   402     PointersToHereCheck pointers_to_here_check_for_value) { | 
|   403   // First, check if a write barrier is even needed. The tests below |   403   // First, check if a write barrier is even needed. The tests below | 
|   404   // catch stores of Smis. |   404   // catch stores of Smis. | 
|   405   Label done; |   405   Label done; | 
|   406  |   406  | 
|   407   // Skip barrier if writing a smi. |   407   // Skip barrier if writing a smi. | 
|   408   if (smi_check == INLINE_SMI_CHECK) { |   408   if (smi_check == INLINE_SMI_CHECK) { | 
|   409     ASSERT_EQ(0, kSmiTag); |   409     DCHECK_EQ(0, kSmiTag); | 
|   410     test(value, Immediate(kSmiTagMask)); |   410     test(value, Immediate(kSmiTagMask)); | 
|   411     j(zero, &done); |   411     j(zero, &done); | 
|   412   } |   412   } | 
|   413  |   413  | 
|   414   // Array access: calculate the destination address in the same manner as |   414   // Array access: calculate the destination address in the same manner as | 
|   415   // KeyedStoreIC::GenerateGeneric.  Multiply a smi by 2 to get an offset |   415   // KeyedStoreIC::GenerateGeneric.  Multiply a smi by 2 to get an offset | 
|   416   // into an array of words. |   416   // into an array of words. | 
|   417   Register dst = index; |   417   Register dst = index; | 
|   418   lea(dst, Operand(object, index, times_half_pointer_size, |   418   lea(dst, Operand(object, index, times_half_pointer_size, | 
|   419                    FixedArray::kHeaderSize - kHeapObjectTag)); |   419                    FixedArray::kHeaderSize - kHeapObjectTag)); | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
|   445   // catch stores of Smis. |   445   // catch stores of Smis. | 
|   446   Label done; |   446   Label done; | 
|   447  |   447  | 
|   448   // Skip barrier if writing a smi. |   448   // Skip barrier if writing a smi. | 
|   449   if (smi_check == INLINE_SMI_CHECK) { |   449   if (smi_check == INLINE_SMI_CHECK) { | 
|   450     JumpIfSmi(value, &done, Label::kNear); |   450     JumpIfSmi(value, &done, Label::kNear); | 
|   451   } |   451   } | 
|   452  |   452  | 
|   453   // Although the object register is tagged, the offset is relative to the start |   453   // Although the object register is tagged, the offset is relative to the start | 
|   454   // of the object, so so offset must be a multiple of kPointerSize. |   454   // of the object, so so offset must be a multiple of kPointerSize. | 
|   455   ASSERT(IsAligned(offset, kPointerSize)); |   455   DCHECK(IsAligned(offset, kPointerSize)); | 
|   456  |   456  | 
|   457   lea(dst, FieldOperand(object, offset)); |   457   lea(dst, FieldOperand(object, offset)); | 
|   458   if (emit_debug_code()) { |   458   if (emit_debug_code()) { | 
|   459     Label ok; |   459     Label ok; | 
|   460     test_b(dst, (1 << kPointerSizeLog2) - 1); |   460     test_b(dst, (1 << kPointerSizeLog2) - 1); | 
|   461     j(zero, &ok, Label::kNear); |   461     j(zero, &ok, Label::kNear); | 
|   462     int3(); |   462     int3(); | 
|   463     bind(&ok); |   463     bind(&ok); | 
|   464   } |   464   } | 
|   465  |   465  | 
| (...skipping 23 matching lines...) Expand all  Loading... | 
|   489   Register value = scratch2; |   489   Register value = scratch2; | 
|   490   if (emit_debug_code()) { |   490   if (emit_debug_code()) { | 
|   491     Label ok; |   491     Label ok; | 
|   492     lea(address, FieldOperand(object, HeapObject::kMapOffset)); |   492     lea(address, FieldOperand(object, HeapObject::kMapOffset)); | 
|   493     test_b(address, (1 << kPointerSizeLog2) - 1); |   493     test_b(address, (1 << kPointerSizeLog2) - 1); | 
|   494     j(zero, &ok, Label::kNear); |   494     j(zero, &ok, Label::kNear); | 
|   495     int3(); |   495     int3(); | 
|   496     bind(&ok); |   496     bind(&ok); | 
|   497   } |   497   } | 
|   498  |   498  | 
|   499   ASSERT(!object.is(value)); |   499   DCHECK(!object.is(value)); | 
|   500   ASSERT(!object.is(address)); |   500   DCHECK(!object.is(address)); | 
|   501   ASSERT(!value.is(address)); |   501   DCHECK(!value.is(address)); | 
|   502   AssertNotSmi(object); |   502   AssertNotSmi(object); | 
|   503  |   503  | 
|   504   if (!FLAG_incremental_marking) { |   504   if (!FLAG_incremental_marking) { | 
|   505     return; |   505     return; | 
|   506   } |   506   } | 
|   507  |   507  | 
|   508   // Compute the address. |   508   // Compute the address. | 
|   509   lea(address, FieldOperand(object, HeapObject::kMapOffset)); |   509   lea(address, FieldOperand(object, HeapObject::kMapOffset)); | 
|   510  |   510  | 
|   511   // A single check of the map's pages interesting flag suffices, since it is |   511   // A single check of the map's pages interesting flag suffices, since it is | 
|   512   // only set during incremental collection, and then it's also guaranteed that |   512   // only set during incremental collection, and then it's also guaranteed that | 
|   513   // the from object's page's interesting flag is also set.  This optimization |   513   // the from object's page's interesting flag is also set.  This optimization | 
|   514   // relies on the fact that maps can never be in new space. |   514   // relies on the fact that maps can never be in new space. | 
|   515   ASSERT(!isolate()->heap()->InNewSpace(*map)); |   515   DCHECK(!isolate()->heap()->InNewSpace(*map)); | 
|   516   CheckPageFlagForMap(map, |   516   CheckPageFlagForMap(map, | 
|   517                       MemoryChunk::kPointersToHereAreInterestingMask, |   517                       MemoryChunk::kPointersToHereAreInterestingMask, | 
|   518                       zero, |   518                       zero, | 
|   519                       &done, |   519                       &done, | 
|   520                       Label::kNear); |   520                       Label::kNear); | 
|   521  |   521  | 
|   522   RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET, |   522   RecordWriteStub stub(isolate(), object, value, address, OMIT_REMEMBERED_SET, | 
|   523                        save_fp); |   523                        save_fp); | 
|   524   CallStub(&stub); |   524   CallStub(&stub); | 
|   525  |   525  | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|   540  |   540  | 
|   541  |   541  | 
|   542 void MacroAssembler::RecordWrite( |   542 void MacroAssembler::RecordWrite( | 
|   543     Register object, |   543     Register object, | 
|   544     Register address, |   544     Register address, | 
|   545     Register value, |   545     Register value, | 
|   546     SaveFPRegsMode fp_mode, |   546     SaveFPRegsMode fp_mode, | 
|   547     RememberedSetAction remembered_set_action, |   547     RememberedSetAction remembered_set_action, | 
|   548     SmiCheck smi_check, |   548     SmiCheck smi_check, | 
|   549     PointersToHereCheck pointers_to_here_check_for_value) { |   549     PointersToHereCheck pointers_to_here_check_for_value) { | 
|   550   ASSERT(!object.is(value)); |   550   DCHECK(!object.is(value)); | 
|   551   ASSERT(!object.is(address)); |   551   DCHECK(!object.is(address)); | 
|   552   ASSERT(!value.is(address)); |   552   DCHECK(!value.is(address)); | 
|   553   AssertNotSmi(object); |   553   AssertNotSmi(object); | 
|   554  |   554  | 
|   555   if (remembered_set_action == OMIT_REMEMBERED_SET && |   555   if (remembered_set_action == OMIT_REMEMBERED_SET && | 
|   556       !FLAG_incremental_marking) { |   556       !FLAG_incremental_marking) { | 
|   557     return; |   557     return; | 
|   558   } |   558   } | 
|   559  |   559  | 
|   560   if (emit_debug_code()) { |   560   if (emit_debug_code()) { | 
|   561     Label ok; |   561     Label ok; | 
|   562     cmp(value, Operand(address, 0)); |   562     cmp(value, Operand(address, 0)); | 
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   950     cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), |   950     cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset), | 
|   951         Immediate(Smi::FromInt(type))); |   951         Immediate(Smi::FromInt(type))); | 
|   952     Check(equal, kStackFrameTypesMustMatch); |   952     Check(equal, kStackFrameTypesMustMatch); | 
|   953   } |   953   } | 
|   954   leave(); |   954   leave(); | 
|   955 } |   955 } | 
|   956  |   956  | 
|   957  |   957  | 
|   958 void MacroAssembler::EnterExitFramePrologue() { |   958 void MacroAssembler::EnterExitFramePrologue() { | 
|   959   // Set up the frame structure on the stack. |   959   // Set up the frame structure on the stack. | 
|   960   ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); |   960   DCHECK(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize); | 
|   961   ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); |   961   DCHECK(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize); | 
|   962   ASSERT(ExitFrameConstants::kCallerFPOffset ==  0 * kPointerSize); |   962   DCHECK(ExitFrameConstants::kCallerFPOffset ==  0 * kPointerSize); | 
|   963   push(ebp); |   963   push(ebp); | 
|   964   mov(ebp, esp); |   964   mov(ebp, esp); | 
|   965  |   965  | 
|   966   // Reserve room for entry stack pointer and push the code object. |   966   // Reserve room for entry stack pointer and push the code object. | 
|   967   ASSERT(ExitFrameConstants::kSPOffset  == -1 * kPointerSize); |   967   DCHECK(ExitFrameConstants::kSPOffset  == -1 * kPointerSize); | 
|   968   push(Immediate(0));  // Saved entry sp, patched before call. |   968   push(Immediate(0));  // Saved entry sp, patched before call. | 
|   969   push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot. |   969   push(Immediate(CodeObject()));  // Accessed from ExitFrame::code_slot. | 
|   970  |   970  | 
|   971   // Save the frame pointer and the context in top. |   971   // Save the frame pointer and the context in top. | 
|   972   ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); |   972   ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); | 
|   973   ExternalReference context_address(Isolate::kContextAddress, isolate()); |   973   ExternalReference context_address(Isolate::kContextAddress, isolate()); | 
|   974   mov(Operand::StaticVariable(c_entry_fp_address), ebp); |   974   mov(Operand::StaticVariable(c_entry_fp_address), ebp); | 
|   975   mov(Operand::StaticVariable(context_address), esi); |   975   mov(Operand::StaticVariable(context_address), esi); | 
|   976 } |   976 } | 
|   977  |   977  | 
|   978  |   978  | 
|   979 void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) { |   979 void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) { | 
|   980   // Optionally save all XMM registers. |   980   // Optionally save all XMM registers. | 
|   981   if (save_doubles) { |   981   if (save_doubles) { | 
|   982     int space = XMMRegister::kMaxNumRegisters * kDoubleSize + |   982     int space = XMMRegister::kMaxNumRegisters * kDoubleSize + | 
|   983                 argc * kPointerSize; |   983                 argc * kPointerSize; | 
|   984     sub(esp, Immediate(space)); |   984     sub(esp, Immediate(space)); | 
|   985     const int offset = -2 * kPointerSize; |   985     const int offset = -2 * kPointerSize; | 
|   986     for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { |   986     for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) { | 
|   987       XMMRegister reg = XMMRegister::from_code(i); |   987       XMMRegister reg = XMMRegister::from_code(i); | 
|   988       movsd(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg); |   988       movsd(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg); | 
|   989     } |   989     } | 
|   990   } else { |   990   } else { | 
|   991     sub(esp, Immediate(argc * kPointerSize)); |   991     sub(esp, Immediate(argc * kPointerSize)); | 
|   992   } |   992   } | 
|   993  |   993  | 
|   994   // Get the required frame alignment for the OS. |   994   // Get the required frame alignment for the OS. | 
|   995   const int kFrameAlignment = base::OS::ActivationFrameAlignment(); |   995   const int kFrameAlignment = base::OS::ActivationFrameAlignment(); | 
|   996   if (kFrameAlignment > 0) { |   996   if (kFrameAlignment > 0) { | 
|   997     ASSERT(IsPowerOf2(kFrameAlignment)); |   997     DCHECK(IsPowerOf2(kFrameAlignment)); | 
|   998     and_(esp, -kFrameAlignment); |   998     and_(esp, -kFrameAlignment); | 
|   999   } |   999   } | 
|  1000  |  1000  | 
|  1001   // Patch the saved entry sp. |  1001   // Patch the saved entry sp. | 
|  1002   mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); |  1002   mov(Operand(ebp, ExitFrameConstants::kSPOffset), esp); | 
|  1003 } |  1003 } | 
|  1004  |  1004  | 
|  1005  |  1005  | 
|  1006 void MacroAssembler::EnterExitFrame(bool save_doubles) { |  1006 void MacroAssembler::EnterExitFrame(bool save_doubles) { | 
|  1007   EnterExitFramePrologue(); |  1007   EnterExitFramePrologue(); | 
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1212   JumpToHandlerEntry(); |  1212   JumpToHandlerEntry(); | 
|  1213 } |  1213 } | 
|  1214  |  1214  | 
|  1215  |  1215  | 
|  1216 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |  1216 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, | 
|  1217                                             Register scratch1, |  1217                                             Register scratch1, | 
|  1218                                             Register scratch2, |  1218                                             Register scratch2, | 
|  1219                                             Label* miss) { |  1219                                             Label* miss) { | 
|  1220   Label same_contexts; |  1220   Label same_contexts; | 
|  1221  |  1221  | 
|  1222   ASSERT(!holder_reg.is(scratch1)); |  1222   DCHECK(!holder_reg.is(scratch1)); | 
|  1223   ASSERT(!holder_reg.is(scratch2)); |  1223   DCHECK(!holder_reg.is(scratch2)); | 
|  1224   ASSERT(!scratch1.is(scratch2)); |  1224   DCHECK(!scratch1.is(scratch2)); | 
|  1225  |  1225  | 
|  1226   // Load current lexical context from the stack frame. |  1226   // Load current lexical context from the stack frame. | 
|  1227   mov(scratch1, Operand(ebp, StandardFrameConstants::kContextOffset)); |  1227   mov(scratch1, Operand(ebp, StandardFrameConstants::kContextOffset)); | 
|  1228  |  1228  | 
|  1229   // When generating debug code, make sure the lexical context is set. |  1229   // When generating debug code, make sure the lexical context is set. | 
|  1230   if (emit_debug_code()) { |  1230   if (emit_debug_code()) { | 
|  1231     cmp(scratch1, Immediate(0)); |  1231     cmp(scratch1, Immediate(0)); | 
|  1232     Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext); |  1232     Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext); | 
|  1233   } |  1233   } | 
|  1234   // Load the native context of the current context. |  1234   // Load the native context of the current context. | 
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1360   for (int i = 0; i < kNumberDictionaryProbes; i++) { |  1360   for (int i = 0; i < kNumberDictionaryProbes; i++) { | 
|  1361     // Use r2 for index calculations and keep the hash intact in r0. |  1361     // Use r2 for index calculations and keep the hash intact in r0. | 
|  1362     mov(r2, r0); |  1362     mov(r2, r0); | 
|  1363     // Compute the masked index: (hash + i + i * i) & mask. |  1363     // Compute the masked index: (hash + i + i * i) & mask. | 
|  1364     if (i > 0) { |  1364     if (i > 0) { | 
|  1365       add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); |  1365       add(r2, Immediate(SeededNumberDictionary::GetProbeOffset(i))); | 
|  1366     } |  1366     } | 
|  1367     and_(r2, r1); |  1367     and_(r2, r1); | 
|  1368  |  1368  | 
|  1369     // Scale the index by multiplying by the entry size. |  1369     // Scale the index by multiplying by the entry size. | 
|  1370     ASSERT(SeededNumberDictionary::kEntrySize == 3); |  1370     DCHECK(SeededNumberDictionary::kEntrySize == 3); | 
|  1371     lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3 |  1371     lea(r2, Operand(r2, r2, times_2, 0));  // r2 = r2 * 3 | 
|  1372  |  1372  | 
|  1373     // Check if the key matches. |  1373     // Check if the key matches. | 
|  1374     cmp(key, FieldOperand(elements, |  1374     cmp(key, FieldOperand(elements, | 
|  1375                           r2, |  1375                           r2, | 
|  1376                           times_pointer_size, |  1376                           times_pointer_size, | 
|  1377                           SeededNumberDictionary::kElementsStartOffset)); |  1377                           SeededNumberDictionary::kElementsStartOffset)); | 
|  1378     if (i != (kNumberDictionaryProbes - 1)) { |  1378     if (i != (kNumberDictionaryProbes - 1)) { | 
|  1379       j(equal, &done); |  1379       j(equal, &done); | 
|  1380     } else { |  1380     } else { | 
|  1381       j(not_equal, miss); |  1381       j(not_equal, miss); | 
|  1382     } |  1382     } | 
|  1383   } |  1383   } | 
|  1384  |  1384  | 
|  1385   bind(&done); |  1385   bind(&done); | 
|  1386   // Check that the value is a normal propety. |  1386   // Check that the value is a normal propety. | 
|  1387   const int kDetailsOffset = |  1387   const int kDetailsOffset = | 
|  1388       SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; |  1388       SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize; | 
|  1389   ASSERT_EQ(NORMAL, 0); |  1389   DCHECK_EQ(NORMAL, 0); | 
|  1390   test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), |  1390   test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), | 
|  1391        Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); |  1391        Immediate(PropertyDetails::TypeField::kMask << kSmiTagSize)); | 
|  1392   j(not_zero, miss); |  1392   j(not_zero, miss); | 
|  1393  |  1393  | 
|  1394   // Get the value at the masked, scaled index. |  1394   // Get the value at the masked, scaled index. | 
|  1395   const int kValueOffset = |  1395   const int kValueOffset = | 
|  1396       SeededNumberDictionary::kElementsStartOffset + kPointerSize; |  1396       SeededNumberDictionary::kElementsStartOffset + kPointerSize; | 
|  1397   mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); |  1397   mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | 
|  1398 } |  1398 } | 
|  1399  |  1399  | 
|  1400  |  1400  | 
|  1401 void MacroAssembler::LoadAllocationTopHelper(Register result, |  1401 void MacroAssembler::LoadAllocationTopHelper(Register result, | 
|  1402                                              Register scratch, |  1402                                              Register scratch, | 
|  1403                                              AllocationFlags flags) { |  1403                                              AllocationFlags flags) { | 
|  1404   ExternalReference allocation_top = |  1404   ExternalReference allocation_top = | 
|  1405       AllocationUtils::GetAllocationTopReference(isolate(), flags); |  1405       AllocationUtils::GetAllocationTopReference(isolate(), flags); | 
|  1406  |  1406  | 
|  1407   // Just return if allocation top is already known. |  1407   // Just return if allocation top is already known. | 
|  1408   if ((flags & RESULT_CONTAINS_TOP) != 0) { |  1408   if ((flags & RESULT_CONTAINS_TOP) != 0) { | 
|  1409     // No use of scratch if allocation top is provided. |  1409     // No use of scratch if allocation top is provided. | 
|  1410     ASSERT(scratch.is(no_reg)); |  1410     DCHECK(scratch.is(no_reg)); | 
|  1411 #ifdef DEBUG |  1411 #ifdef DEBUG | 
|  1412     // Assert that result actually contains top on entry. |  1412     // Assert that result actually contains top on entry. | 
|  1413     cmp(result, Operand::StaticVariable(allocation_top)); |  1413     cmp(result, Operand::StaticVariable(allocation_top)); | 
|  1414     Check(equal, kUnexpectedAllocationTop); |  1414     Check(equal, kUnexpectedAllocationTop); | 
|  1415 #endif |  1415 #endif | 
|  1416     return; |  1416     return; | 
|  1417   } |  1417   } | 
|  1418  |  1418  | 
|  1419   // Move address of new object to result. Use scratch register if available. |  1419   // Move address of new object to result. Use scratch register if available. | 
|  1420   if (scratch.is(no_reg)) { |  1420   if (scratch.is(no_reg)) { | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
|  1445   } |  1445   } | 
|  1446 } |  1446 } | 
|  1447  |  1447  | 
|  1448  |  1448  | 
|  1449 void MacroAssembler::Allocate(int object_size, |  1449 void MacroAssembler::Allocate(int object_size, | 
|  1450                               Register result, |  1450                               Register result, | 
|  1451                               Register result_end, |  1451                               Register result_end, | 
|  1452                               Register scratch, |  1452                               Register scratch, | 
|  1453                               Label* gc_required, |  1453                               Label* gc_required, | 
|  1454                               AllocationFlags flags) { |  1454                               AllocationFlags flags) { | 
|  1455   ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0); |  1455   DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0); | 
|  1456   ASSERT(object_size <= Page::kMaxRegularHeapObjectSize); |  1456   DCHECK(object_size <= Page::kMaxRegularHeapObjectSize); | 
|  1457   if (!FLAG_inline_new) { |  1457   if (!FLAG_inline_new) { | 
|  1458     if (emit_debug_code()) { |  1458     if (emit_debug_code()) { | 
|  1459       // Trash the registers to simulate an allocation failure. |  1459       // Trash the registers to simulate an allocation failure. | 
|  1460       mov(result, Immediate(0x7091)); |  1460       mov(result, Immediate(0x7091)); | 
|  1461       if (result_end.is_valid()) { |  1461       if (result_end.is_valid()) { | 
|  1462         mov(result_end, Immediate(0x7191)); |  1462         mov(result_end, Immediate(0x7191)); | 
|  1463       } |  1463       } | 
|  1464       if (scratch.is_valid()) { |  1464       if (scratch.is_valid()) { | 
|  1465         mov(scratch, Immediate(0x7291)); |  1465         mov(scratch, Immediate(0x7291)); | 
|  1466       } |  1466       } | 
|  1467     } |  1467     } | 
|  1468     jmp(gc_required); |  1468     jmp(gc_required); | 
|  1469     return; |  1469     return; | 
|  1470   } |  1470   } | 
|  1471   ASSERT(!result.is(result_end)); |  1471   DCHECK(!result.is(result_end)); | 
|  1472  |  1472  | 
|  1473   // Load address of new object into result. |  1473   // Load address of new object into result. | 
|  1474   LoadAllocationTopHelper(result, scratch, flags); |  1474   LoadAllocationTopHelper(result, scratch, flags); | 
|  1475  |  1475  | 
|  1476   ExternalReference allocation_limit = |  1476   ExternalReference allocation_limit = | 
|  1477       AllocationUtils::GetAllocationLimitReference(isolate(), flags); |  1477       AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 
|  1478  |  1478  | 
|  1479   // Align the next allocation. Storing the filler map without checking top is |  1479   // Align the next allocation. Storing the filler map without checking top is | 
|  1480   // safe in new-space because the limit of the heap is aligned there. |  1480   // safe in new-space because the limit of the heap is aligned there. | 
|  1481   if ((flags & DOUBLE_ALIGNMENT) != 0) { |  1481   if ((flags & DOUBLE_ALIGNMENT) != 0) { | 
|  1482     ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); |  1482     DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0); | 
|  1483     ASSERT(kPointerAlignment * 2 == kDoubleAlignment); |  1483     DCHECK(kPointerAlignment * 2 == kDoubleAlignment); | 
|  1484     Label aligned; |  1484     Label aligned; | 
|  1485     test(result, Immediate(kDoubleAlignmentMask)); |  1485     test(result, Immediate(kDoubleAlignmentMask)); | 
|  1486     j(zero, &aligned, Label::kNear); |  1486     j(zero, &aligned, Label::kNear); | 
|  1487     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { |  1487     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { | 
|  1488       cmp(result, Operand::StaticVariable(allocation_limit)); |  1488       cmp(result, Operand::StaticVariable(allocation_limit)); | 
|  1489       j(above_equal, gc_required); |  1489       j(above_equal, gc_required); | 
|  1490     } |  1490     } | 
|  1491     mov(Operand(result, 0), |  1491     mov(Operand(result, 0), | 
|  1492         Immediate(isolate()->factory()->one_pointer_filler_map())); |  1492         Immediate(isolate()->factory()->one_pointer_filler_map())); | 
|  1493     add(result, Immediate(kDoubleSize / 2)); |  1493     add(result, Immediate(kDoubleSize / 2)); | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
|  1509  |  1509  | 
|  1510   // Tag result if requested. |  1510   // Tag result if requested. | 
|  1511   bool tag_result = (flags & TAG_OBJECT) != 0; |  1511   bool tag_result = (flags & TAG_OBJECT) != 0; | 
|  1512   if (top_reg.is(result)) { |  1512   if (top_reg.is(result)) { | 
|  1513     if (tag_result) { |  1513     if (tag_result) { | 
|  1514       sub(result, Immediate(object_size - kHeapObjectTag)); |  1514       sub(result, Immediate(object_size - kHeapObjectTag)); | 
|  1515     } else { |  1515     } else { | 
|  1516       sub(result, Immediate(object_size)); |  1516       sub(result, Immediate(object_size)); | 
|  1517     } |  1517     } | 
|  1518   } else if (tag_result) { |  1518   } else if (tag_result) { | 
|  1519     ASSERT(kHeapObjectTag == 1); |  1519     DCHECK(kHeapObjectTag == 1); | 
|  1520     inc(result); |  1520     inc(result); | 
|  1521   } |  1521   } | 
|  1522 } |  1522 } | 
|  1523  |  1523  | 
|  1524  |  1524  | 
|  1525 void MacroAssembler::Allocate(int header_size, |  1525 void MacroAssembler::Allocate(int header_size, | 
|  1526                               ScaleFactor element_size, |  1526                               ScaleFactor element_size, | 
|  1527                               Register element_count, |  1527                               Register element_count, | 
|  1528                               RegisterValueType element_count_type, |  1528                               RegisterValueType element_count_type, | 
|  1529                               Register result, |  1529                               Register result, | 
|  1530                               Register result_end, |  1530                               Register result_end, | 
|  1531                               Register scratch, |  1531                               Register scratch, | 
|  1532                               Label* gc_required, |  1532                               Label* gc_required, | 
|  1533                               AllocationFlags flags) { |  1533                               AllocationFlags flags) { | 
|  1534   ASSERT((flags & SIZE_IN_WORDS) == 0); |  1534   DCHECK((flags & SIZE_IN_WORDS) == 0); | 
|  1535   if (!FLAG_inline_new) { |  1535   if (!FLAG_inline_new) { | 
|  1536     if (emit_debug_code()) { |  1536     if (emit_debug_code()) { | 
|  1537       // Trash the registers to simulate an allocation failure. |  1537       // Trash the registers to simulate an allocation failure. | 
|  1538       mov(result, Immediate(0x7091)); |  1538       mov(result, Immediate(0x7091)); | 
|  1539       mov(result_end, Immediate(0x7191)); |  1539       mov(result_end, Immediate(0x7191)); | 
|  1540       if (scratch.is_valid()) { |  1540       if (scratch.is_valid()) { | 
|  1541         mov(scratch, Immediate(0x7291)); |  1541         mov(scratch, Immediate(0x7291)); | 
|  1542       } |  1542       } | 
|  1543       // Register element_count is not modified by the function. |  1543       // Register element_count is not modified by the function. | 
|  1544     } |  1544     } | 
|  1545     jmp(gc_required); |  1545     jmp(gc_required); | 
|  1546     return; |  1546     return; | 
|  1547   } |  1547   } | 
|  1548   ASSERT(!result.is(result_end)); |  1548   DCHECK(!result.is(result_end)); | 
|  1549  |  1549  | 
|  1550   // Load address of new object into result. |  1550   // Load address of new object into result. | 
|  1551   LoadAllocationTopHelper(result, scratch, flags); |  1551   LoadAllocationTopHelper(result, scratch, flags); | 
|  1552  |  1552  | 
|  1553   ExternalReference allocation_limit = |  1553   ExternalReference allocation_limit = | 
|  1554       AllocationUtils::GetAllocationLimitReference(isolate(), flags); |  1554       AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 
|  1555  |  1555  | 
|  1556   // Align the next allocation. Storing the filler map without checking top is |  1556   // Align the next allocation. Storing the filler map without checking top is | 
|  1557   // safe in new-space because the limit of the heap is aligned there. |  1557   // safe in new-space because the limit of the heap is aligned there. | 
|  1558   if ((flags & DOUBLE_ALIGNMENT) != 0) { |  1558   if ((flags & DOUBLE_ALIGNMENT) != 0) { | 
|  1559     ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); |  1559     DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0); | 
|  1560     ASSERT(kPointerAlignment * 2 == kDoubleAlignment); |  1560     DCHECK(kPointerAlignment * 2 == kDoubleAlignment); | 
|  1561     Label aligned; |  1561     Label aligned; | 
|  1562     test(result, Immediate(kDoubleAlignmentMask)); |  1562     test(result, Immediate(kDoubleAlignmentMask)); | 
|  1563     j(zero, &aligned, Label::kNear); |  1563     j(zero, &aligned, Label::kNear); | 
|  1564     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { |  1564     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { | 
|  1565       cmp(result, Operand::StaticVariable(allocation_limit)); |  1565       cmp(result, Operand::StaticVariable(allocation_limit)); | 
|  1566       j(above_equal, gc_required); |  1566       j(above_equal, gc_required); | 
|  1567     } |  1567     } | 
|  1568     mov(Operand(result, 0), |  1568     mov(Operand(result, 0), | 
|  1569         Immediate(isolate()->factory()->one_pointer_filler_map())); |  1569         Immediate(isolate()->factory()->one_pointer_filler_map())); | 
|  1570     add(result, Immediate(kDoubleSize / 2)); |  1570     add(result, Immediate(kDoubleSize / 2)); | 
|  1571     bind(&aligned); |  1571     bind(&aligned); | 
|  1572   } |  1572   } | 
|  1573  |  1573  | 
|  1574   // Calculate new top and bail out if space is exhausted. |  1574   // Calculate new top and bail out if space is exhausted. | 
|  1575   // We assume that element_count*element_size + header_size does not |  1575   // We assume that element_count*element_size + header_size does not | 
|  1576   // overflow. |  1576   // overflow. | 
|  1577   if (element_count_type == REGISTER_VALUE_IS_SMI) { |  1577   if (element_count_type == REGISTER_VALUE_IS_SMI) { | 
|  1578     STATIC_ASSERT(static_cast<ScaleFactor>(times_2 - 1) == times_1); |  1578     STATIC_ASSERT(static_cast<ScaleFactor>(times_2 - 1) == times_1); | 
|  1579     STATIC_ASSERT(static_cast<ScaleFactor>(times_4 - 1) == times_2); |  1579     STATIC_ASSERT(static_cast<ScaleFactor>(times_4 - 1) == times_2); | 
|  1580     STATIC_ASSERT(static_cast<ScaleFactor>(times_8 - 1) == times_4); |  1580     STATIC_ASSERT(static_cast<ScaleFactor>(times_8 - 1) == times_4); | 
|  1581     ASSERT(element_size >= times_2); |  1581     DCHECK(element_size >= times_2); | 
|  1582     ASSERT(kSmiTagSize == 1); |  1582     DCHECK(kSmiTagSize == 1); | 
|  1583     element_size = static_cast<ScaleFactor>(element_size - 1); |  1583     element_size = static_cast<ScaleFactor>(element_size - 1); | 
|  1584   } else { |  1584   } else { | 
|  1585     ASSERT(element_count_type == REGISTER_VALUE_IS_INT32); |  1585     DCHECK(element_count_type == REGISTER_VALUE_IS_INT32); | 
|  1586   } |  1586   } | 
|  1587   lea(result_end, Operand(element_count, element_size, header_size)); |  1587   lea(result_end, Operand(element_count, element_size, header_size)); | 
|  1588   add(result_end, result); |  1588   add(result_end, result); | 
|  1589   j(carry, gc_required); |  1589   j(carry, gc_required); | 
|  1590   cmp(result_end, Operand::StaticVariable(allocation_limit)); |  1590   cmp(result_end, Operand::StaticVariable(allocation_limit)); | 
|  1591   j(above, gc_required); |  1591   j(above, gc_required); | 
|  1592  |  1592  | 
|  1593   if ((flags & TAG_OBJECT) != 0) { |  1593   if ((flags & TAG_OBJECT) != 0) { | 
|  1594     ASSERT(kHeapObjectTag == 1); |  1594     DCHECK(kHeapObjectTag == 1); | 
|  1595     inc(result); |  1595     inc(result); | 
|  1596   } |  1596   } | 
|  1597  |  1597  | 
|  1598   // Update allocation top. |  1598   // Update allocation top. | 
|  1599   UpdateAllocationTopHelper(result_end, scratch, flags); |  1599   UpdateAllocationTopHelper(result_end, scratch, flags); | 
|  1600 } |  1600 } | 
|  1601  |  1601  | 
|  1602  |  1602  | 
|  1603 void MacroAssembler::Allocate(Register object_size, |  1603 void MacroAssembler::Allocate(Register object_size, | 
|  1604                               Register result, |  1604                               Register result, | 
|  1605                               Register result_end, |  1605                               Register result_end, | 
|  1606                               Register scratch, |  1606                               Register scratch, | 
|  1607                               Label* gc_required, |  1607                               Label* gc_required, | 
|  1608                               AllocationFlags flags) { |  1608                               AllocationFlags flags) { | 
|  1609   ASSERT((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0); |  1609   DCHECK((flags & (RESULT_CONTAINS_TOP | SIZE_IN_WORDS)) == 0); | 
|  1610   if (!FLAG_inline_new) { |  1610   if (!FLAG_inline_new) { | 
|  1611     if (emit_debug_code()) { |  1611     if (emit_debug_code()) { | 
|  1612       // Trash the registers to simulate an allocation failure. |  1612       // Trash the registers to simulate an allocation failure. | 
|  1613       mov(result, Immediate(0x7091)); |  1613       mov(result, Immediate(0x7091)); | 
|  1614       mov(result_end, Immediate(0x7191)); |  1614       mov(result_end, Immediate(0x7191)); | 
|  1615       if (scratch.is_valid()) { |  1615       if (scratch.is_valid()) { | 
|  1616         mov(scratch, Immediate(0x7291)); |  1616         mov(scratch, Immediate(0x7291)); | 
|  1617       } |  1617       } | 
|  1618       // object_size is left unchanged by this function. |  1618       // object_size is left unchanged by this function. | 
|  1619     } |  1619     } | 
|  1620     jmp(gc_required); |  1620     jmp(gc_required); | 
|  1621     return; |  1621     return; | 
|  1622   } |  1622   } | 
|  1623   ASSERT(!result.is(result_end)); |  1623   DCHECK(!result.is(result_end)); | 
|  1624  |  1624  | 
|  1625   // Load address of new object into result. |  1625   // Load address of new object into result. | 
|  1626   LoadAllocationTopHelper(result, scratch, flags); |  1626   LoadAllocationTopHelper(result, scratch, flags); | 
|  1627  |  1627  | 
|  1628   ExternalReference allocation_limit = |  1628   ExternalReference allocation_limit = | 
|  1629       AllocationUtils::GetAllocationLimitReference(isolate(), flags); |  1629       AllocationUtils::GetAllocationLimitReference(isolate(), flags); | 
|  1630  |  1630  | 
|  1631   // Align the next allocation. Storing the filler map without checking top is |  1631   // Align the next allocation. Storing the filler map without checking top is | 
|  1632   // safe in new-space because the limit of the heap is aligned there. |  1632   // safe in new-space because the limit of the heap is aligned there. | 
|  1633   if ((flags & DOUBLE_ALIGNMENT) != 0) { |  1633   if ((flags & DOUBLE_ALIGNMENT) != 0) { | 
|  1634     ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0); |  1634     DCHECK((flags & PRETENURE_OLD_POINTER_SPACE) == 0); | 
|  1635     ASSERT(kPointerAlignment * 2 == kDoubleAlignment); |  1635     DCHECK(kPointerAlignment * 2 == kDoubleAlignment); | 
|  1636     Label aligned; |  1636     Label aligned; | 
|  1637     test(result, Immediate(kDoubleAlignmentMask)); |  1637     test(result, Immediate(kDoubleAlignmentMask)); | 
|  1638     j(zero, &aligned, Label::kNear); |  1638     j(zero, &aligned, Label::kNear); | 
|  1639     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { |  1639     if ((flags & PRETENURE_OLD_DATA_SPACE) != 0) { | 
|  1640       cmp(result, Operand::StaticVariable(allocation_limit)); |  1640       cmp(result, Operand::StaticVariable(allocation_limit)); | 
|  1641       j(above_equal, gc_required); |  1641       j(above_equal, gc_required); | 
|  1642     } |  1642     } | 
|  1643     mov(Operand(result, 0), |  1643     mov(Operand(result, 0), | 
|  1644         Immediate(isolate()->factory()->one_pointer_filler_map())); |  1644         Immediate(isolate()->factory()->one_pointer_filler_map())); | 
|  1645     add(result, Immediate(kDoubleSize / 2)); |  1645     add(result, Immediate(kDoubleSize / 2)); | 
|  1646     bind(&aligned); |  1646     bind(&aligned); | 
|  1647   } |  1647   } | 
|  1648  |  1648  | 
|  1649   // Calculate new top and bail out if space is exhausted. |  1649   // Calculate new top and bail out if space is exhausted. | 
|  1650   if (!object_size.is(result_end)) { |  1650   if (!object_size.is(result_end)) { | 
|  1651     mov(result_end, object_size); |  1651     mov(result_end, object_size); | 
|  1652   } |  1652   } | 
|  1653   add(result_end, result); |  1653   add(result_end, result); | 
|  1654   j(carry, gc_required); |  1654   j(carry, gc_required); | 
|  1655   cmp(result_end, Operand::StaticVariable(allocation_limit)); |  1655   cmp(result_end, Operand::StaticVariable(allocation_limit)); | 
|  1656   j(above, gc_required); |  1656   j(above, gc_required); | 
|  1657  |  1657  | 
|  1658   // Tag result if requested. |  1658   // Tag result if requested. | 
|  1659   if ((flags & TAG_OBJECT) != 0) { |  1659   if ((flags & TAG_OBJECT) != 0) { | 
|  1660     ASSERT(kHeapObjectTag == 1); |  1660     DCHECK(kHeapObjectTag == 1); | 
|  1661     inc(result); |  1661     inc(result); | 
|  1662   } |  1662   } | 
|  1663  |  1663  | 
|  1664   // Update allocation top. |  1664   // Update allocation top. | 
|  1665   UpdateAllocationTopHelper(result_end, scratch, flags); |  1665   UpdateAllocationTopHelper(result_end, scratch, flags); | 
|  1666 } |  1666 } | 
|  1667  |  1667  | 
|  1668  |  1668  | 
|  1669 void MacroAssembler::UndoAllocationInNewSpace(Register object) { |  1669 void MacroAssembler::UndoAllocationInNewSpace(Register object) { | 
|  1670   ExternalReference new_space_allocation_top = |  1670   ExternalReference new_space_allocation_top = | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
|  1699  |  1699  | 
|  1700  |  1700  | 
|  1701 void MacroAssembler::AllocateTwoByteString(Register result, |  1701 void MacroAssembler::AllocateTwoByteString(Register result, | 
|  1702                                            Register length, |  1702                                            Register length, | 
|  1703                                            Register scratch1, |  1703                                            Register scratch1, | 
|  1704                                            Register scratch2, |  1704                                            Register scratch2, | 
|  1705                                            Register scratch3, |  1705                                            Register scratch3, | 
|  1706                                            Label* gc_required) { |  1706                                            Label* gc_required) { | 
|  1707   // Calculate the number of bytes needed for the characters in the string while |  1707   // Calculate the number of bytes needed for the characters in the string while | 
|  1708   // observing object alignment. |  1708   // observing object alignment. | 
|  1709   ASSERT((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); |  1709   DCHECK((SeqTwoByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 
|  1710   ASSERT(kShortSize == 2); |  1710   DCHECK(kShortSize == 2); | 
|  1711   // scratch1 = length * 2 + kObjectAlignmentMask. |  1711   // scratch1 = length * 2 + kObjectAlignmentMask. | 
|  1712   lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask)); |  1712   lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask)); | 
|  1713   and_(scratch1, Immediate(~kObjectAlignmentMask)); |  1713   and_(scratch1, Immediate(~kObjectAlignmentMask)); | 
|  1714  |  1714  | 
|  1715   // Allocate two byte string in new space. |  1715   // Allocate two byte string in new space. | 
|  1716   Allocate(SeqTwoByteString::kHeaderSize, |  1716   Allocate(SeqTwoByteString::kHeaderSize, | 
|  1717            times_1, |  1717            times_1, | 
|  1718            scratch1, |  1718            scratch1, | 
|  1719            REGISTER_VALUE_IS_INT32, |  1719            REGISTER_VALUE_IS_INT32, | 
|  1720            result, |  1720            result, | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|  1735  |  1735  | 
|  1736  |  1736  | 
|  1737 void MacroAssembler::AllocateAsciiString(Register result, |  1737 void MacroAssembler::AllocateAsciiString(Register result, | 
|  1738                                          Register length, |  1738                                          Register length, | 
|  1739                                          Register scratch1, |  1739                                          Register scratch1, | 
|  1740                                          Register scratch2, |  1740                                          Register scratch2, | 
|  1741                                          Register scratch3, |  1741                                          Register scratch3, | 
|  1742                                          Label* gc_required) { |  1742                                          Label* gc_required) { | 
|  1743   // Calculate the number of bytes needed for the characters in the string while |  1743   // Calculate the number of bytes needed for the characters in the string while | 
|  1744   // observing object alignment. |  1744   // observing object alignment. | 
|  1745   ASSERT((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); |  1745   DCHECK((SeqOneByteString::kHeaderSize & kObjectAlignmentMask) == 0); | 
|  1746   mov(scratch1, length); |  1746   mov(scratch1, length); | 
|  1747   ASSERT(kCharSize == 1); |  1747   DCHECK(kCharSize == 1); | 
|  1748   add(scratch1, Immediate(kObjectAlignmentMask)); |  1748   add(scratch1, Immediate(kObjectAlignmentMask)); | 
|  1749   and_(scratch1, Immediate(~kObjectAlignmentMask)); |  1749   and_(scratch1, Immediate(~kObjectAlignmentMask)); | 
|  1750  |  1750  | 
|  1751   // Allocate ASCII string in new space. |  1751   // Allocate ASCII string in new space. | 
|  1752   Allocate(SeqOneByteString::kHeaderSize, |  1752   Allocate(SeqOneByteString::kHeaderSize, | 
|  1753            times_1, |  1753            times_1, | 
|  1754            scratch1, |  1754            scratch1, | 
|  1755            REGISTER_VALUE_IS_INT32, |  1755            REGISTER_VALUE_IS_INT32, | 
|  1756            result, |  1756            result, | 
|  1757            scratch2, |  1757            scratch2, | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  1768   mov(FieldOperand(result, String::kHashFieldOffset), |  1768   mov(FieldOperand(result, String::kHashFieldOffset), | 
|  1769       Immediate(String::kEmptyHashField)); |  1769       Immediate(String::kEmptyHashField)); | 
|  1770 } |  1770 } | 
|  1771  |  1771  | 
|  1772  |  1772  | 
|  1773 void MacroAssembler::AllocateAsciiString(Register result, |  1773 void MacroAssembler::AllocateAsciiString(Register result, | 
|  1774                                          int length, |  1774                                          int length, | 
|  1775                                          Register scratch1, |  1775                                          Register scratch1, | 
|  1776                                          Register scratch2, |  1776                                          Register scratch2, | 
|  1777                                          Label* gc_required) { |  1777                                          Label* gc_required) { | 
|  1778   ASSERT(length > 0); |  1778   DCHECK(length > 0); | 
|  1779  |  1779  | 
|  1780   // Allocate ASCII string in new space. |  1780   // Allocate ASCII string in new space. | 
|  1781   Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2, |  1781   Allocate(SeqOneByteString::SizeFor(length), result, scratch1, scratch2, | 
|  1782            gc_required, TAG_OBJECT); |  1782            gc_required, TAG_OBJECT); | 
|  1783  |  1783  | 
|  1784   // Set the map, length and hash field. |  1784   // Set the map, length and hash field. | 
|  1785   mov(FieldOperand(result, HeapObject::kMapOffset), |  1785   mov(FieldOperand(result, HeapObject::kMapOffset), | 
|  1786       Immediate(isolate()->factory()->ascii_string_map())); |  1786       Immediate(isolate()->factory()->ascii_string_map())); | 
|  1787   mov(FieldOperand(result, String::kLengthOffset), |  1787   mov(FieldOperand(result, String::kLengthOffset), | 
|  1788       Immediate(Smi::FromInt(length))); |  1788       Immediate(Smi::FromInt(length))); | 
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1856 // Many variants of movsb, loop unrolling, word moves, and indexed operands |  1856 // Many variants of movsb, loop unrolling, word moves, and indexed operands | 
|  1857 // have been tried here already, and this is fastest. |  1857 // have been tried here already, and this is fastest. | 
|  1858 // A simpler loop is faster on small copies, but 30% slower on large ones. |  1858 // A simpler loop is faster on small copies, but 30% slower on large ones. | 
|  1859 // The cld() instruction must have been emitted, to set the direction flag(), |  1859 // The cld() instruction must have been emitted, to set the direction flag(), | 
|  1860 // before calling this function. |  1860 // before calling this function. | 
|  1861 void MacroAssembler::CopyBytes(Register source, |  1861 void MacroAssembler::CopyBytes(Register source, | 
|  1862                                Register destination, |  1862                                Register destination, | 
|  1863                                Register length, |  1863                                Register length, | 
|  1864                                Register scratch) { |  1864                                Register scratch) { | 
|  1865   Label short_loop, len4, len8, len12, done, short_string; |  1865   Label short_loop, len4, len8, len12, done, short_string; | 
|  1866   ASSERT(source.is(esi)); |  1866   DCHECK(source.is(esi)); | 
|  1867   ASSERT(destination.is(edi)); |  1867   DCHECK(destination.is(edi)); | 
|  1868   ASSERT(length.is(ecx)); |  1868   DCHECK(length.is(ecx)); | 
|  1869   cmp(length, Immediate(4)); |  1869   cmp(length, Immediate(4)); | 
|  1870   j(below, &short_string, Label::kNear); |  1870   j(below, &short_string, Label::kNear); | 
|  1871  |  1871  | 
|  1872   // Because source is 4-byte aligned in our uses of this function, |  1872   // Because source is 4-byte aligned in our uses of this function, | 
|  1873   // we keep source aligned for the rep_movs call by copying the odd bytes |  1873   // we keep source aligned for the rep_movs call by copying the odd bytes | 
|  1874   // at the end of the ranges. |  1874   // at the end of the ranges. | 
|  1875   mov(scratch, Operand(source, length, times_1, -4)); |  1875   mov(scratch, Operand(source, length, times_1, -4)); | 
|  1876   mov(Operand(destination, length, times_1, -4), scratch); |  1876   mov(Operand(destination, length, times_1, -4), scratch); | 
|  1877  |  1877  | 
|  1878   cmp(length, Immediate(8)); |  1878   cmp(length, Immediate(8)); | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1928   bind(&entry); |  1928   bind(&entry); | 
|  1929   cmp(start_offset, end_offset); |  1929   cmp(start_offset, end_offset); | 
|  1930   j(less, &loop); |  1930   j(less, &loop); | 
|  1931 } |  1931 } | 
|  1932  |  1932  | 
|  1933  |  1933  | 
|  1934 void MacroAssembler::BooleanBitTest(Register object, |  1934 void MacroAssembler::BooleanBitTest(Register object, | 
|  1935                                     int field_offset, |  1935                                     int field_offset, | 
|  1936                                     int bit_index) { |  1936                                     int bit_index) { | 
|  1937   bit_index += kSmiTagSize + kSmiShiftSize; |  1937   bit_index += kSmiTagSize + kSmiShiftSize; | 
|  1938   ASSERT(IsPowerOf2(kBitsPerByte)); |  1938   DCHECK(IsPowerOf2(kBitsPerByte)); | 
|  1939   int byte_index = bit_index / kBitsPerByte; |  1939   int byte_index = bit_index / kBitsPerByte; | 
|  1940   int byte_bit_index = bit_index & (kBitsPerByte - 1); |  1940   int byte_bit_index = bit_index & (kBitsPerByte - 1); | 
|  1941   test_b(FieldOperand(object, field_offset + byte_index), |  1941   test_b(FieldOperand(object, field_offset + byte_index), | 
|  1942          static_cast<byte>(1 << byte_bit_index)); |  1942          static_cast<byte>(1 << byte_bit_index)); | 
|  1943 } |  1943 } | 
|  1944  |  1944  | 
|  1945  |  1945  | 
|  1946  |  1946  | 
|  1947 void MacroAssembler::NegativeZeroTest(Register result, |  1947 void MacroAssembler::NegativeZeroTest(Register result, | 
|  1948                                       Register op, |  1948                                       Register op, | 
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2024     bind(&non_instance); |  2024     bind(&non_instance); | 
|  2025     mov(result, FieldOperand(result, Map::kConstructorOffset)); |  2025     mov(result, FieldOperand(result, Map::kConstructorOffset)); | 
|  2026   } |  2026   } | 
|  2027  |  2027  | 
|  2028   // All done. |  2028   // All done. | 
|  2029   bind(&done); |  2029   bind(&done); | 
|  2030 } |  2030 } | 
|  2031  |  2031  | 
|  2032  |  2032  | 
|  2033 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) { |  2033 void MacroAssembler::CallStub(CodeStub* stub, TypeFeedbackId ast_id) { | 
|  2034   ASSERT(AllowThisStubCall(stub));  // Calls are not allowed in some stubs. |  2034   DCHECK(AllowThisStubCall(stub));  // Calls are not allowed in some stubs. | 
|  2035   call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); |  2035   call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); | 
|  2036 } |  2036 } | 
|  2037  |  2037  | 
|  2038  |  2038  | 
|  2039 void MacroAssembler::TailCallStub(CodeStub* stub) { |  2039 void MacroAssembler::TailCallStub(CodeStub* stub) { | 
|  2040   jmp(stub->GetCode(), RelocInfo::CODE_TARGET); |  2040   jmp(stub->GetCode(), RelocInfo::CODE_TARGET); | 
|  2041 } |  2041 } | 
|  2042  |  2042  | 
|  2043  |  2043  | 
|  2044 void MacroAssembler::StubReturn(int argc) { |  2044 void MacroAssembler::StubReturn(int argc) { | 
|  2045   ASSERT(argc >= 1 && generating_stub()); |  2045   DCHECK(argc >= 1 && generating_stub()); | 
|  2046   ret((argc - 1) * kPointerSize); |  2046   ret((argc - 1) * kPointerSize); | 
|  2047 } |  2047 } | 
|  2048  |  2048  | 
|  2049  |  2049  | 
|  2050 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { |  2050 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { | 
|  2051   return has_frame_ || !stub->SometimesSetsUpAFrame(); |  2051   return has_frame_ || !stub->SometimesSetsUpAFrame(); | 
|  2052 } |  2052 } | 
|  2053  |  2053  | 
|  2054  |  2054  | 
|  2055 void MacroAssembler::IndexFromHash(Register hash, Register index) { |  2055 void MacroAssembler::IndexFromHash(Register hash, Register index) { | 
|  2056   // The assert checks that the constants for the maximum number of digits |  2056   // The assert checks that the constants for the maximum number of digits | 
|  2057   // for an array index cached in the hash field and the number of bits |  2057   // for an array index cached in the hash field and the number of bits | 
|  2058   // reserved for it does not conflict. |  2058   // reserved for it does not conflict. | 
|  2059   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) < |  2059   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) < | 
|  2060          (1 << String::kArrayIndexValueBits)); |  2060          (1 << String::kArrayIndexValueBits)); | 
|  2061   if (!index.is(hash)) { |  2061   if (!index.is(hash)) { | 
|  2062     mov(index, hash); |  2062     mov(index, hash); | 
|  2063   } |  2063   } | 
|  2064   DecodeFieldToSmi<String::ArrayIndexValueBits>(index); |  2064   DecodeFieldToSmi<String::ArrayIndexValueBits>(index); | 
|  2065 } |  2065 } | 
|  2066  |  2066  | 
|  2067  |  2067  | 
|  2068 void MacroAssembler::CallRuntime(const Runtime::Function* f, |  2068 void MacroAssembler::CallRuntime(const Runtime::Function* f, | 
|  2069                                  int num_arguments, |  2069                                  int num_arguments, | 
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2135     int stack_space, |  2135     int stack_space, | 
|  2136     Operand return_value_operand, |  2136     Operand return_value_operand, | 
|  2137     Operand* context_restore_operand) { |  2137     Operand* context_restore_operand) { | 
|  2138   ExternalReference next_address = |  2138   ExternalReference next_address = | 
|  2139       ExternalReference::handle_scope_next_address(isolate()); |  2139       ExternalReference::handle_scope_next_address(isolate()); | 
|  2140   ExternalReference limit_address = |  2140   ExternalReference limit_address = | 
|  2141       ExternalReference::handle_scope_limit_address(isolate()); |  2141       ExternalReference::handle_scope_limit_address(isolate()); | 
|  2142   ExternalReference level_address = |  2142   ExternalReference level_address = | 
|  2143       ExternalReference::handle_scope_level_address(isolate()); |  2143       ExternalReference::handle_scope_level_address(isolate()); | 
|  2144  |  2144  | 
|  2145   ASSERT(edx.is(function_address)); |  2145   DCHECK(edx.is(function_address)); | 
|  2146   // Allocate HandleScope in callee-save registers. |  2146   // Allocate HandleScope in callee-save registers. | 
|  2147   mov(ebx, Operand::StaticVariable(next_address)); |  2147   mov(ebx, Operand::StaticVariable(next_address)); | 
|  2148   mov(edi, Operand::StaticVariable(limit_address)); |  2148   mov(edi, Operand::StaticVariable(limit_address)); | 
|  2149   add(Operand::StaticVariable(level_address), Immediate(1)); |  2149   add(Operand::StaticVariable(level_address), Immediate(1)); | 
|  2150  |  2150  | 
|  2151   if (FLAG_log_timer_events) { |  2151   if (FLAG_log_timer_events) { | 
|  2152     FrameScope frame(this, StackFrame::MANUAL); |  2152     FrameScope frame(this, StackFrame::MANUAL); | 
|  2153     PushSafepointRegisters(); |  2153     PushSafepointRegisters(); | 
|  2154     PrepareCallCFunction(1, eax); |  2154     PrepareCallCFunction(1, eax); | 
|  2155     mov(Operand(esp, 0), |  2155     mov(Operand(esp, 0), | 
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2292                                     const Operand& code_operand, |  2292                                     const Operand& code_operand, | 
|  2293                                     Label* done, |  2293                                     Label* done, | 
|  2294                                     bool* definitely_mismatches, |  2294                                     bool* definitely_mismatches, | 
|  2295                                     InvokeFlag flag, |  2295                                     InvokeFlag flag, | 
|  2296                                     Label::Distance done_near, |  2296                                     Label::Distance done_near, | 
|  2297                                     const CallWrapper& call_wrapper) { |  2297                                     const CallWrapper& call_wrapper) { | 
|  2298   bool definitely_matches = false; |  2298   bool definitely_matches = false; | 
|  2299   *definitely_mismatches = false; |  2299   *definitely_mismatches = false; | 
|  2300   Label invoke; |  2300   Label invoke; | 
|  2301   if (expected.is_immediate()) { |  2301   if (expected.is_immediate()) { | 
|  2302     ASSERT(actual.is_immediate()); |  2302     DCHECK(actual.is_immediate()); | 
|  2303     if (expected.immediate() == actual.immediate()) { |  2303     if (expected.immediate() == actual.immediate()) { | 
|  2304       definitely_matches = true; |  2304       definitely_matches = true; | 
|  2305     } else { |  2305     } else { | 
|  2306       mov(eax, actual.immediate()); |  2306       mov(eax, actual.immediate()); | 
|  2307       const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; |  2307       const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 
|  2308       if (expected.immediate() == sentinel) { |  2308       if (expected.immediate() == sentinel) { | 
|  2309         // Don't worry about adapting arguments for builtins that |  2309         // Don't worry about adapting arguments for builtins that | 
|  2310         // don't want that done. Skip adaption code by making it look |  2310         // don't want that done. Skip adaption code by making it look | 
|  2311         // like we have a match between expected and actual number of |  2311         // like we have a match between expected and actual number of | 
|  2312         // arguments. |  2312         // arguments. | 
|  2313         definitely_matches = true; |  2313         definitely_matches = true; | 
|  2314       } else { |  2314       } else { | 
|  2315         *definitely_mismatches = true; |  2315         *definitely_mismatches = true; | 
|  2316         mov(ebx, expected.immediate()); |  2316         mov(ebx, expected.immediate()); | 
|  2317       } |  2317       } | 
|  2318     } |  2318     } | 
|  2319   } else { |  2319   } else { | 
|  2320     if (actual.is_immediate()) { |  2320     if (actual.is_immediate()) { | 
|  2321       // Expected is in register, actual is immediate. This is the |  2321       // Expected is in register, actual is immediate. This is the | 
|  2322       // case when we invoke function values without going through the |  2322       // case when we invoke function values without going through the | 
|  2323       // IC mechanism. |  2323       // IC mechanism. | 
|  2324       cmp(expected.reg(), actual.immediate()); |  2324       cmp(expected.reg(), actual.immediate()); | 
|  2325       j(equal, &invoke); |  2325       j(equal, &invoke); | 
|  2326       ASSERT(expected.reg().is(ebx)); |  2326       DCHECK(expected.reg().is(ebx)); | 
|  2327       mov(eax, actual.immediate()); |  2327       mov(eax, actual.immediate()); | 
|  2328     } else if (!expected.reg().is(actual.reg())) { |  2328     } else if (!expected.reg().is(actual.reg())) { | 
|  2329       // Both expected and actual are in (different) registers. This |  2329       // Both expected and actual are in (different) registers. This | 
|  2330       // is the case when we invoke functions using call and apply. |  2330       // is the case when we invoke functions using call and apply. | 
|  2331       cmp(expected.reg(), actual.reg()); |  2331       cmp(expected.reg(), actual.reg()); | 
|  2332       j(equal, &invoke); |  2332       j(equal, &invoke); | 
|  2333       ASSERT(actual.reg().is(eax)); |  2333       DCHECK(actual.reg().is(eax)); | 
|  2334       ASSERT(expected.reg().is(ebx)); |  2334       DCHECK(expected.reg().is(ebx)); | 
|  2335     } |  2335     } | 
|  2336   } |  2336   } | 
|  2337  |  2337  | 
|  2338   if (!definitely_matches) { |  2338   if (!definitely_matches) { | 
|  2339     Handle<Code> adaptor = |  2339     Handle<Code> adaptor = | 
|  2340         isolate()->builtins()->ArgumentsAdaptorTrampoline(); |  2340         isolate()->builtins()->ArgumentsAdaptorTrampoline(); | 
|  2341     if (!code_constant.is_null()) { |  2341     if (!code_constant.is_null()) { | 
|  2342       mov(edx, Immediate(code_constant)); |  2342       mov(edx, Immediate(code_constant)); | 
|  2343       add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag)); |  2343       add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 
|  2344     } else if (!code_operand.is_reg(edx)) { |  2344     } else if (!code_operand.is_reg(edx)) { | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|  2359   } |  2359   } | 
|  2360 } |  2360 } | 
|  2361  |  2361  | 
|  2362  |  2362  | 
|  2363 void MacroAssembler::InvokeCode(const Operand& code, |  2363 void MacroAssembler::InvokeCode(const Operand& code, | 
|  2364                                 const ParameterCount& expected, |  2364                                 const ParameterCount& expected, | 
|  2365                                 const ParameterCount& actual, |  2365                                 const ParameterCount& actual, | 
|  2366                                 InvokeFlag flag, |  2366                                 InvokeFlag flag, | 
|  2367                                 const CallWrapper& call_wrapper) { |  2367                                 const CallWrapper& call_wrapper) { | 
|  2368   // You can't call a function without a valid frame. |  2368   // You can't call a function without a valid frame. | 
|  2369   ASSERT(flag == JUMP_FUNCTION || has_frame()); |  2369   DCHECK(flag == JUMP_FUNCTION || has_frame()); | 
|  2370  |  2370  | 
|  2371   Label done; |  2371   Label done; | 
|  2372   bool definitely_mismatches = false; |  2372   bool definitely_mismatches = false; | 
|  2373   InvokePrologue(expected, actual, Handle<Code>::null(), code, |  2373   InvokePrologue(expected, actual, Handle<Code>::null(), code, | 
|  2374                  &done, &definitely_mismatches, flag, Label::kNear, |  2374                  &done, &definitely_mismatches, flag, Label::kNear, | 
|  2375                  call_wrapper); |  2375                  call_wrapper); | 
|  2376   if (!definitely_mismatches) { |  2376   if (!definitely_mismatches) { | 
|  2377     if (flag == CALL_FUNCTION) { |  2377     if (flag == CALL_FUNCTION) { | 
|  2378       call_wrapper.BeforeCall(CallSize(code)); |  2378       call_wrapper.BeforeCall(CallSize(code)); | 
|  2379       call(code); |  2379       call(code); | 
|  2380       call_wrapper.AfterCall(); |  2380       call_wrapper.AfterCall(); | 
|  2381     } else { |  2381     } else { | 
|  2382       ASSERT(flag == JUMP_FUNCTION); |  2382       DCHECK(flag == JUMP_FUNCTION); | 
|  2383       jmp(code); |  2383       jmp(code); | 
|  2384     } |  2384     } | 
|  2385     bind(&done); |  2385     bind(&done); | 
|  2386   } |  2386   } | 
|  2387 } |  2387 } | 
|  2388  |  2388  | 
|  2389  |  2389  | 
|  2390 void MacroAssembler::InvokeFunction(Register fun, |  2390 void MacroAssembler::InvokeFunction(Register fun, | 
|  2391                                     const ParameterCount& actual, |  2391                                     const ParameterCount& actual, | 
|  2392                                     InvokeFlag flag, |  2392                                     InvokeFlag flag, | 
|  2393                                     const CallWrapper& call_wrapper) { |  2393                                     const CallWrapper& call_wrapper) { | 
|  2394   // You can't call a function without a valid frame. |  2394   // You can't call a function without a valid frame. | 
|  2395   ASSERT(flag == JUMP_FUNCTION || has_frame()); |  2395   DCHECK(flag == JUMP_FUNCTION || has_frame()); | 
|  2396  |  2396  | 
|  2397   ASSERT(fun.is(edi)); |  2397   DCHECK(fun.is(edi)); | 
|  2398   mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |  2398   mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 
|  2399   mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |  2399   mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 
|  2400   mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); |  2400   mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); | 
|  2401   SmiUntag(ebx); |  2401   SmiUntag(ebx); | 
|  2402  |  2402  | 
|  2403   ParameterCount expected(ebx); |  2403   ParameterCount expected(ebx); | 
|  2404   InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |  2404   InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 
|  2405              expected, actual, flag, call_wrapper); |  2405              expected, actual, flag, call_wrapper); | 
|  2406 } |  2406 } | 
|  2407  |  2407  | 
|  2408  |  2408  | 
|  2409 void MacroAssembler::InvokeFunction(Register fun, |  2409 void MacroAssembler::InvokeFunction(Register fun, | 
|  2410                                     const ParameterCount& expected, |  2410                                     const ParameterCount& expected, | 
|  2411                                     const ParameterCount& actual, |  2411                                     const ParameterCount& actual, | 
|  2412                                     InvokeFlag flag, |  2412                                     InvokeFlag flag, | 
|  2413                                     const CallWrapper& call_wrapper) { |  2413                                     const CallWrapper& call_wrapper) { | 
|  2414   // You can't call a function without a valid frame. |  2414   // You can't call a function without a valid frame. | 
|  2415   ASSERT(flag == JUMP_FUNCTION || has_frame()); |  2415   DCHECK(flag == JUMP_FUNCTION || has_frame()); | 
|  2416  |  2416  | 
|  2417   ASSERT(fun.is(edi)); |  2417   DCHECK(fun.is(edi)); | 
|  2418   mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |  2418   mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 
|  2419  |  2419  | 
|  2420   InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |  2420   InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 
|  2421              expected, actual, flag, call_wrapper); |  2421              expected, actual, flag, call_wrapper); | 
|  2422 } |  2422 } | 
|  2423  |  2423  | 
|  2424  |  2424  | 
|  2425 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |  2425 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, | 
|  2426                                     const ParameterCount& expected, |  2426                                     const ParameterCount& expected, | 
|  2427                                     const ParameterCount& actual, |  2427                                     const ParameterCount& actual, | 
|  2428                                     InvokeFlag flag, |  2428                                     InvokeFlag flag, | 
|  2429                                     const CallWrapper& call_wrapper) { |  2429                                     const CallWrapper& call_wrapper) { | 
|  2430   LoadHeapObject(edi, function); |  2430   LoadHeapObject(edi, function); | 
|  2431   InvokeFunction(edi, expected, actual, flag, call_wrapper); |  2431   InvokeFunction(edi, expected, actual, flag, call_wrapper); | 
|  2432 } |  2432 } | 
|  2433  |  2433  | 
|  2434  |  2434  | 
|  2435 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |  2435 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 
|  2436                                    InvokeFlag flag, |  2436                                    InvokeFlag flag, | 
|  2437                                    const CallWrapper& call_wrapper) { |  2437                                    const CallWrapper& call_wrapper) { | 
|  2438   // You can't call a builtin without a valid frame. |  2438   // You can't call a builtin without a valid frame. | 
|  2439   ASSERT(flag == JUMP_FUNCTION || has_frame()); |  2439   DCHECK(flag == JUMP_FUNCTION || has_frame()); | 
|  2440  |  2440  | 
|  2441   // Rely on the assertion to check that the number of provided |  2441   // Rely on the assertion to check that the number of provided | 
|  2442   // arguments match the expected number of arguments. Fake a |  2442   // arguments match the expected number of arguments. Fake a | 
|  2443   // parameter count to avoid emitting code to do the check. |  2443   // parameter count to avoid emitting code to do the check. | 
|  2444   ParameterCount expected(0); |  2444   ParameterCount expected(0); | 
|  2445   GetBuiltinFunction(edi, id); |  2445   GetBuiltinFunction(edi, id); | 
|  2446   InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |  2446   InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 
|  2447              expected, expected, flag, call_wrapper); |  2447              expected, expected, flag, call_wrapper); | 
|  2448 } |  2448 } | 
|  2449  |  2449  | 
|  2450  |  2450  | 
|  2451 void MacroAssembler::GetBuiltinFunction(Register target, |  2451 void MacroAssembler::GetBuiltinFunction(Register target, | 
|  2452                                         Builtins::JavaScript id) { |  2452                                         Builtins::JavaScript id) { | 
|  2453   // Load the JavaScript builtin function from the builtins object. |  2453   // Load the JavaScript builtin function from the builtins object. | 
|  2454   mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |  2454   mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 
|  2455   mov(target, FieldOperand(target, GlobalObject::kBuiltinsOffset)); |  2455   mov(target, FieldOperand(target, GlobalObject::kBuiltinsOffset)); | 
|  2456   mov(target, FieldOperand(target, |  2456   mov(target, FieldOperand(target, | 
|  2457                            JSBuiltinsObject::OffsetOfFunctionWithId(id))); |  2457                            JSBuiltinsObject::OffsetOfFunctionWithId(id))); | 
|  2458 } |  2458 } | 
|  2459  |  2459  | 
|  2460  |  2460  | 
|  2461 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { |  2461 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { | 
|  2462   ASSERT(!target.is(edi)); |  2462   DCHECK(!target.is(edi)); | 
|  2463   // Load the JavaScript builtin function from the builtins object. |  2463   // Load the JavaScript builtin function from the builtins object. | 
|  2464   GetBuiltinFunction(edi, id); |  2464   GetBuiltinFunction(edi, id); | 
|  2465   // Load the code entry point from the function into the target register. |  2465   // Load the code entry point from the function into the target register. | 
|  2466   mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset)); |  2466   mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset)); | 
|  2467 } |  2467 } | 
|  2468  |  2468  | 
|  2469  |  2469  | 
|  2470 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { |  2470 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { | 
|  2471   if (context_chain_length > 0) { |  2471   if (context_chain_length > 0) { | 
|  2472     // Move up the chain of contexts to the context containing the slot. |  2472     // Move up the chain of contexts to the context containing the slot. | 
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2565  |  2565  | 
|  2566 Operand MacroAssembler::SafepointRegisterSlot(Register reg) { |  2566 Operand MacroAssembler::SafepointRegisterSlot(Register reg) { | 
|  2567   return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); |  2567   return Operand(esp, SafepointRegisterStackIndex(reg.code()) * kPointerSize); | 
|  2568 } |  2568 } | 
|  2569  |  2569  | 
|  2570  |  2570  | 
|  2571 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { |  2571 int MacroAssembler::SafepointRegisterStackIndex(int reg_code) { | 
|  2572   // The registers are pushed starting with the lowest encoding, |  2572   // The registers are pushed starting with the lowest encoding, | 
|  2573   // which means that lowest encodings are furthest away from |  2573   // which means that lowest encodings are furthest away from | 
|  2574   // the stack pointer. |  2574   // the stack pointer. | 
|  2575   ASSERT(reg_code >= 0 && reg_code < kNumSafepointRegisters); |  2575   DCHECK(reg_code >= 0 && reg_code < kNumSafepointRegisters); | 
|  2576   return kNumSafepointRegisters - reg_code - 1; |  2576   return kNumSafepointRegisters - reg_code - 1; | 
|  2577 } |  2577 } | 
|  2578  |  2578  | 
|  2579  |  2579  | 
|  2580 void MacroAssembler::LoadHeapObject(Register result, |  2580 void MacroAssembler::LoadHeapObject(Register result, | 
|  2581                                     Handle<HeapObject> object) { |  2581                                     Handle<HeapObject> object) { | 
|  2582   AllowDeferredHandleDereference embedding_raw_address; |  2582   AllowDeferredHandleDereference embedding_raw_address; | 
|  2583   if (isolate()->heap()->InNewSpace(*object)) { |  2583   if (isolate()->heap()->InNewSpace(*object)) { | 
|  2584     Handle<Cell> cell = isolate()->factory()->NewCell(object); |  2584     Handle<Cell> cell = isolate()->factory()->NewCell(object); | 
|  2585     mov(result, Operand::ForCell(cell)); |  2585     mov(result, Operand::ForCell(cell)); | 
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2673  |  2673  | 
|  2674  |  2674  | 
|  2675 void MacroAssembler::SetCounter(StatsCounter* counter, int value) { |  2675 void MacroAssembler::SetCounter(StatsCounter* counter, int value) { | 
|  2676   if (FLAG_native_code_counters && counter->Enabled()) { |  2676   if (FLAG_native_code_counters && counter->Enabled()) { | 
|  2677     mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value)); |  2677     mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value)); | 
|  2678   } |  2678   } | 
|  2679 } |  2679 } | 
|  2680  |  2680  | 
|  2681  |  2681  | 
|  2682 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { |  2682 void MacroAssembler::IncrementCounter(StatsCounter* counter, int value) { | 
|  2683   ASSERT(value > 0); |  2683   DCHECK(value > 0); | 
|  2684   if (FLAG_native_code_counters && counter->Enabled()) { |  2684   if (FLAG_native_code_counters && counter->Enabled()) { | 
|  2685     Operand operand = Operand::StaticVariable(ExternalReference(counter)); |  2685     Operand operand = Operand::StaticVariable(ExternalReference(counter)); | 
|  2686     if (value == 1) { |  2686     if (value == 1) { | 
|  2687       inc(operand); |  2687       inc(operand); | 
|  2688     } else { |  2688     } else { | 
|  2689       add(operand, Immediate(value)); |  2689       add(operand, Immediate(value)); | 
|  2690     } |  2690     } | 
|  2691   } |  2691   } | 
|  2692 } |  2692 } | 
|  2693  |  2693  | 
|  2694  |  2694  | 
|  2695 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { |  2695 void MacroAssembler::DecrementCounter(StatsCounter* counter, int value) { | 
|  2696   ASSERT(value > 0); |  2696   DCHECK(value > 0); | 
|  2697   if (FLAG_native_code_counters && counter->Enabled()) { |  2697   if (FLAG_native_code_counters && counter->Enabled()) { | 
|  2698     Operand operand = Operand::StaticVariable(ExternalReference(counter)); |  2698     Operand operand = Operand::StaticVariable(ExternalReference(counter)); | 
|  2699     if (value == 1) { |  2699     if (value == 1) { | 
|  2700       dec(operand); |  2700       dec(operand); | 
|  2701     } else { |  2701     } else { | 
|  2702       sub(operand, Immediate(value)); |  2702       sub(operand, Immediate(value)); | 
|  2703     } |  2703     } | 
|  2704   } |  2704   } | 
|  2705 } |  2705 } | 
|  2706  |  2706  | 
|  2707  |  2707  | 
|  2708 void MacroAssembler::IncrementCounter(Condition cc, |  2708 void MacroAssembler::IncrementCounter(Condition cc, | 
|  2709                                       StatsCounter* counter, |  2709                                       StatsCounter* counter, | 
|  2710                                       int value) { |  2710                                       int value) { | 
|  2711   ASSERT(value > 0); |  2711   DCHECK(value > 0); | 
|  2712   if (FLAG_native_code_counters && counter->Enabled()) { |  2712   if (FLAG_native_code_counters && counter->Enabled()) { | 
|  2713     Label skip; |  2713     Label skip; | 
|  2714     j(NegateCondition(cc), &skip); |  2714     j(NegateCondition(cc), &skip); | 
|  2715     pushfd(); |  2715     pushfd(); | 
|  2716     IncrementCounter(counter, value); |  2716     IncrementCounter(counter, value); | 
|  2717     popfd(); |  2717     popfd(); | 
|  2718     bind(&skip); |  2718     bind(&skip); | 
|  2719   } |  2719   } | 
|  2720 } |  2720 } | 
|  2721  |  2721  | 
|  2722  |  2722  | 
|  2723 void MacroAssembler::DecrementCounter(Condition cc, |  2723 void MacroAssembler::DecrementCounter(Condition cc, | 
|  2724                                       StatsCounter* counter, |  2724                                       StatsCounter* counter, | 
|  2725                                       int value) { |  2725                                       int value) { | 
|  2726   ASSERT(value > 0); |  2726   DCHECK(value > 0); | 
|  2727   if (FLAG_native_code_counters && counter->Enabled()) { |  2727   if (FLAG_native_code_counters && counter->Enabled()) { | 
|  2728     Label skip; |  2728     Label skip; | 
|  2729     j(NegateCondition(cc), &skip); |  2729     j(NegateCondition(cc), &skip); | 
|  2730     pushfd(); |  2730     pushfd(); | 
|  2731     DecrementCounter(counter, value); |  2731     DecrementCounter(counter, value); | 
|  2732     popfd(); |  2732     popfd(); | 
|  2733     bind(&skip); |  2733     bind(&skip); | 
|  2734   } |  2734   } | 
|  2735 } |  2735 } | 
|  2736  |  2736  | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
|  2765   Abort(reason); |  2765   Abort(reason); | 
|  2766   // will not return here |  2766   // will not return here | 
|  2767   bind(&L); |  2767   bind(&L); | 
|  2768 } |  2768 } | 
|  2769  |  2769  | 
|  2770  |  2770  | 
|  2771 void MacroAssembler::CheckStackAlignment() { |  2771 void MacroAssembler::CheckStackAlignment() { | 
|  2772   int frame_alignment = base::OS::ActivationFrameAlignment(); |  2772   int frame_alignment = base::OS::ActivationFrameAlignment(); | 
|  2773   int frame_alignment_mask = frame_alignment - 1; |  2773   int frame_alignment_mask = frame_alignment - 1; | 
|  2774   if (frame_alignment > kPointerSize) { |  2774   if (frame_alignment > kPointerSize) { | 
|  2775     ASSERT(IsPowerOf2(frame_alignment)); |  2775     DCHECK(IsPowerOf2(frame_alignment)); | 
|  2776     Label alignment_as_expected; |  2776     Label alignment_as_expected; | 
|  2777     test(esp, Immediate(frame_alignment_mask)); |  2777     test(esp, Immediate(frame_alignment_mask)); | 
|  2778     j(zero, &alignment_as_expected); |  2778     j(zero, &alignment_as_expected); | 
|  2779     // Abort if stack is not aligned. |  2779     // Abort if stack is not aligned. | 
|  2780     int3(); |  2780     int3(); | 
|  2781     bind(&alignment_as_expected); |  2781     bind(&alignment_as_expected); | 
|  2782   } |  2782   } | 
|  2783 } |  2783 } | 
|  2784  |  2784  | 
|  2785  |  2785  | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2820  |  2820  | 
|  2821 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { |  2821 void MacroAssembler::NumberOfOwnDescriptors(Register dst, Register map) { | 
|  2822   mov(dst, FieldOperand(map, Map::kBitField3Offset)); |  2822   mov(dst, FieldOperand(map, Map::kBitField3Offset)); | 
|  2823   DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); |  2823   DecodeField<Map::NumberOfOwnDescriptorsBits>(dst); | 
|  2824 } |  2824 } | 
|  2825  |  2825  | 
|  2826  |  2826  | 
|  2827 void MacroAssembler::LoadPowerOf2(XMMRegister dst, |  2827 void MacroAssembler::LoadPowerOf2(XMMRegister dst, | 
|  2828                                   Register scratch, |  2828                                   Register scratch, | 
|  2829                                   int power) { |  2829                                   int power) { | 
|  2830   ASSERT(is_uintn(power + HeapNumber::kExponentBias, |  2830   DCHECK(is_uintn(power + HeapNumber::kExponentBias, | 
|  2831                   HeapNumber::kExponentBits)); |  2831                   HeapNumber::kExponentBits)); | 
|  2832   mov(scratch, Immediate(power + HeapNumber::kExponentBias)); |  2832   mov(scratch, Immediate(power + HeapNumber::kExponentBias)); | 
|  2833   movd(dst, scratch); |  2833   movd(dst, scratch); | 
|  2834   psllq(dst, HeapNumber::kMantissaBits); |  2834   psllq(dst, HeapNumber::kMantissaBits); | 
|  2835 } |  2835 } | 
|  2836  |  2836  | 
|  2837  |  2837  | 
|  2838 void MacroAssembler::LookupNumberStringCache(Register object, |  2838 void MacroAssembler::LookupNumberStringCache(Register object, | 
|  2839                                              Register result, |  2839                                              Register result, | 
|  2840                                              Register scratch1, |  2840                                              Register scratch1, | 
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2940   mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset)); |  2940   mov(scratch2, FieldOperand(object2, HeapObject::kMapOffset)); | 
|  2941   movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); |  2941   movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset)); | 
|  2942   movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); |  2942   movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset)); | 
|  2943  |  2943  | 
|  2944   // Check that both are flat ASCII strings. |  2944   // Check that both are flat ASCII strings. | 
|  2945   const int kFlatAsciiStringMask = |  2945   const int kFlatAsciiStringMask = | 
|  2946       kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; |  2946       kIsNotStringMask | kStringRepresentationMask | kStringEncodingMask; | 
|  2947   const int kFlatAsciiStringTag = |  2947   const int kFlatAsciiStringTag = | 
|  2948       kStringTag | kOneByteStringTag | kSeqStringTag; |  2948       kStringTag | kOneByteStringTag | kSeqStringTag; | 
|  2949   // Interleave bits from both instance types and compare them in one check. |  2949   // Interleave bits from both instance types and compare them in one check. | 
|  2950   ASSERT_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); |  2950   DCHECK_EQ(0, kFlatAsciiStringMask & (kFlatAsciiStringMask << 3)); | 
|  2951   and_(scratch1, kFlatAsciiStringMask); |  2951   and_(scratch1, kFlatAsciiStringMask); | 
|  2952   and_(scratch2, kFlatAsciiStringMask); |  2952   and_(scratch2, kFlatAsciiStringMask); | 
|  2953   lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); |  2953   lea(scratch1, Operand(scratch1, scratch2, times_8, 0)); | 
|  2954   cmp(scratch1, kFlatAsciiStringTag | (kFlatAsciiStringTag << 3)); |  2954   cmp(scratch1, kFlatAsciiStringTag | (kFlatAsciiStringTag << 3)); | 
|  2955   j(not_equal, failure); |  2955   j(not_equal, failure); | 
|  2956 } |  2956 } | 
|  2957  |  2957  | 
|  2958  |  2958  | 
|  2959 void MacroAssembler::JumpIfNotUniqueName(Operand operand, |  2959 void MacroAssembler::JumpIfNotUniqueName(Operand operand, | 
|  2960                                          Label* not_unique_name, |  2960                                          Label* not_unique_name, | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3005 } |  3005 } | 
|  3006  |  3006  | 
|  3007  |  3007  | 
|  3008 void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { |  3008 void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) { | 
|  3009   int frame_alignment = base::OS::ActivationFrameAlignment(); |  3009   int frame_alignment = base::OS::ActivationFrameAlignment(); | 
|  3010   if (frame_alignment != 0) { |  3010   if (frame_alignment != 0) { | 
|  3011     // Make stack end at alignment and make room for num_arguments words |  3011     // Make stack end at alignment and make room for num_arguments words | 
|  3012     // and the original value of esp. |  3012     // and the original value of esp. | 
|  3013     mov(scratch, esp); |  3013     mov(scratch, esp); | 
|  3014     sub(esp, Immediate((num_arguments + 1) * kPointerSize)); |  3014     sub(esp, Immediate((num_arguments + 1) * kPointerSize)); | 
|  3015     ASSERT(IsPowerOf2(frame_alignment)); |  3015     DCHECK(IsPowerOf2(frame_alignment)); | 
|  3016     and_(esp, -frame_alignment); |  3016     and_(esp, -frame_alignment); | 
|  3017     mov(Operand(esp, num_arguments * kPointerSize), scratch); |  3017     mov(Operand(esp, num_arguments * kPointerSize), scratch); | 
|  3018   } else { |  3018   } else { | 
|  3019     sub(esp, Immediate(num_arguments * kPointerSize)); |  3019     sub(esp, Immediate(num_arguments * kPointerSize)); | 
|  3020   } |  3020   } | 
|  3021 } |  3021 } | 
|  3022  |  3022  | 
|  3023  |  3023  | 
|  3024 void MacroAssembler::CallCFunction(ExternalReference function, |  3024 void MacroAssembler::CallCFunction(ExternalReference function, | 
|  3025                                    int num_arguments) { |  3025                                    int num_arguments) { | 
|  3026   // Trashing eax is ok as it will be the return value. |  3026   // Trashing eax is ok as it will be the return value. | 
|  3027   mov(eax, Immediate(function)); |  3027   mov(eax, Immediate(function)); | 
|  3028   CallCFunction(eax, num_arguments); |  3028   CallCFunction(eax, num_arguments); | 
|  3029 } |  3029 } | 
|  3030  |  3030  | 
|  3031  |  3031  | 
|  3032 void MacroAssembler::CallCFunction(Register function, |  3032 void MacroAssembler::CallCFunction(Register function, | 
|  3033                                    int num_arguments) { |  3033                                    int num_arguments) { | 
|  3034   ASSERT(has_frame()); |  3034   DCHECK(has_frame()); | 
|  3035   // Check stack alignment. |  3035   // Check stack alignment. | 
|  3036   if (emit_debug_code()) { |  3036   if (emit_debug_code()) { | 
|  3037     CheckStackAlignment(); |  3037     CheckStackAlignment(); | 
|  3038   } |  3038   } | 
|  3039  |  3039  | 
|  3040   call(function); |  3040   call(function); | 
|  3041   if (base::OS::ActivationFrameAlignment() != 0) { |  3041   if (base::OS::ActivationFrameAlignment() != 0) { | 
|  3042     mov(esp, Operand(esp, num_arguments * kPointerSize)); |  3042     mov(esp, Operand(esp, num_arguments * kPointerSize)); | 
|  3043   } else { |  3043   } else { | 
|  3044     add(esp, Immediate(num_arguments * kPointerSize)); |  3044     add(esp, Immediate(num_arguments * kPointerSize)); | 
| (...skipping 30 matching lines...) Expand all  Loading... | 
|  3075 #endif |  3075 #endif | 
|  3076  |  3076  | 
|  3077  |  3077  | 
|  3078 CodePatcher::CodePatcher(byte* address, int size) |  3078 CodePatcher::CodePatcher(byte* address, int size) | 
|  3079     : address_(address), |  3079     : address_(address), | 
|  3080       size_(size), |  3080       size_(size), | 
|  3081       masm_(NULL, address, size + Assembler::kGap) { |  3081       masm_(NULL, address, size + Assembler::kGap) { | 
|  3082   // Create a new macro assembler pointing to the address of the code to patch. |  3082   // Create a new macro assembler pointing to the address of the code to patch. | 
|  3083   // The size is adjusted with kGap on order for the assembler to generate size |  3083   // The size is adjusted with kGap on order for the assembler to generate size | 
|  3084   // bytes of instructions without failing with buffer size constraints. |  3084   // bytes of instructions without failing with buffer size constraints. | 
|  3085   ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |  3085   DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 
|  3086 } |  3086 } | 
|  3087  |  3087  | 
|  3088  |  3088  | 
|  3089 CodePatcher::~CodePatcher() { |  3089 CodePatcher::~CodePatcher() { | 
|  3090   // Indicate that code has changed. |  3090   // Indicate that code has changed. | 
|  3091   CpuFeatures::FlushICache(address_, size_); |  3091   CpuFeatures::FlushICache(address_, size_); | 
|  3092  |  3092  | 
|  3093   // Check that the code was patched as expected. |  3093   // Check that the code was patched as expected. | 
|  3094   ASSERT(masm_.pc_ == address_ + size_); |  3094   DCHECK(masm_.pc_ == address_ + size_); | 
|  3095   ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |  3095   DCHECK(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 
|  3096 } |  3096 } | 
|  3097  |  3097  | 
|  3098  |  3098  | 
|  3099 void MacroAssembler::CheckPageFlag( |  3099 void MacroAssembler::CheckPageFlag( | 
|  3100     Register object, |  3100     Register object, | 
|  3101     Register scratch, |  3101     Register scratch, | 
|  3102     int mask, |  3102     int mask, | 
|  3103     Condition cc, |  3103     Condition cc, | 
|  3104     Label* condition_met, |  3104     Label* condition_met, | 
|  3105     Label::Distance condition_met_distance) { |  3105     Label::Distance condition_met_distance) { | 
|  3106   ASSERT(cc == zero || cc == not_zero); |  3106   DCHECK(cc == zero || cc == not_zero); | 
|  3107   if (scratch.is(object)) { |  3107   if (scratch.is(object)) { | 
|  3108     and_(scratch, Immediate(~Page::kPageAlignmentMask)); |  3108     and_(scratch, Immediate(~Page::kPageAlignmentMask)); | 
|  3109   } else { |  3109   } else { | 
|  3110     mov(scratch, Immediate(~Page::kPageAlignmentMask)); |  3110     mov(scratch, Immediate(~Page::kPageAlignmentMask)); | 
|  3111     and_(scratch, object); |  3111     and_(scratch, object); | 
|  3112   } |  3112   } | 
|  3113   if (mask < (1 << kBitsPerByte)) { |  3113   if (mask < (1 << kBitsPerByte)) { | 
|  3114     test_b(Operand(scratch, MemoryChunk::kFlagsOffset), |  3114     test_b(Operand(scratch, MemoryChunk::kFlagsOffset), | 
|  3115            static_cast<uint8_t>(mask)); |  3115            static_cast<uint8_t>(mask)); | 
|  3116   } else { |  3116   } else { | 
|  3117     test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask)); |  3117     test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask)); | 
|  3118   } |  3118   } | 
|  3119   j(cc, condition_met, condition_met_distance); |  3119   j(cc, condition_met, condition_met_distance); | 
|  3120 } |  3120 } | 
|  3121  |  3121  | 
|  3122  |  3122  | 
|  3123 void MacroAssembler::CheckPageFlagForMap( |  3123 void MacroAssembler::CheckPageFlagForMap( | 
|  3124     Handle<Map> map, |  3124     Handle<Map> map, | 
|  3125     int mask, |  3125     int mask, | 
|  3126     Condition cc, |  3126     Condition cc, | 
|  3127     Label* condition_met, |  3127     Label* condition_met, | 
|  3128     Label::Distance condition_met_distance) { |  3128     Label::Distance condition_met_distance) { | 
|  3129   ASSERT(cc == zero || cc == not_zero); |  3129   DCHECK(cc == zero || cc == not_zero); | 
|  3130   Page* page = Page::FromAddress(map->address()); |  3130   Page* page = Page::FromAddress(map->address()); | 
|  3131   ExternalReference reference(ExternalReference::page_flags(page)); |  3131   ExternalReference reference(ExternalReference::page_flags(page)); | 
|  3132   // The inlined static address check of the page's flags relies |  3132   // The inlined static address check of the page's flags relies | 
|  3133   // on maps never being compacted. |  3133   // on maps never being compacted. | 
|  3134   ASSERT(!isolate()->heap()->mark_compact_collector()-> |  3134   DCHECK(!isolate()->heap()->mark_compact_collector()-> | 
|  3135          IsOnEvacuationCandidate(*map)); |  3135          IsOnEvacuationCandidate(*map)); | 
|  3136   if (mask < (1 << kBitsPerByte)) { |  3136   if (mask < (1 << kBitsPerByte)) { | 
|  3137     test_b(Operand::StaticVariable(reference), static_cast<uint8_t>(mask)); |  3137     test_b(Operand::StaticVariable(reference), static_cast<uint8_t>(mask)); | 
|  3138   } else { |  3138   } else { | 
|  3139     test(Operand::StaticVariable(reference), Immediate(mask)); |  3139     test(Operand::StaticVariable(reference), Immediate(mask)); | 
|  3140   } |  3140   } | 
|  3141   j(cc, condition_met, condition_met_distance); |  3141   j(cc, condition_met, condition_met_distance); | 
|  3142 } |  3142 } | 
|  3143  |  3143  | 
|  3144  |  3144  | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|  3155  |  3155  | 
|  3156  |  3156  | 
|  3157 void MacroAssembler::JumpIfBlack(Register object, |  3157 void MacroAssembler::JumpIfBlack(Register object, | 
|  3158                                  Register scratch0, |  3158                                  Register scratch0, | 
|  3159                                  Register scratch1, |  3159                                  Register scratch1, | 
|  3160                                  Label* on_black, |  3160                                  Label* on_black, | 
|  3161                                  Label::Distance on_black_near) { |  3161                                  Label::Distance on_black_near) { | 
|  3162   HasColor(object, scratch0, scratch1, |  3162   HasColor(object, scratch0, scratch1, | 
|  3163            on_black, on_black_near, |  3163            on_black, on_black_near, | 
|  3164            1, 0);  // kBlackBitPattern. |  3164            1, 0);  // kBlackBitPattern. | 
|  3165   ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); |  3165   DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); | 
|  3166 } |  3166 } | 
|  3167  |  3167  | 
|  3168  |  3168  | 
|  3169 void MacroAssembler::HasColor(Register object, |  3169 void MacroAssembler::HasColor(Register object, | 
|  3170                               Register bitmap_scratch, |  3170                               Register bitmap_scratch, | 
|  3171                               Register mask_scratch, |  3171                               Register mask_scratch, | 
|  3172                               Label* has_color, |  3172                               Label* has_color, | 
|  3173                               Label::Distance has_color_distance, |  3173                               Label::Distance has_color_distance, | 
|  3174                               int first_bit, |  3174                               int first_bit, | 
|  3175                               int second_bit) { |  3175                               int second_bit) { | 
|  3176   ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, ecx)); |  3176   DCHECK(!AreAliased(object, bitmap_scratch, mask_scratch, ecx)); | 
|  3177  |  3177  | 
|  3178   GetMarkBits(object, bitmap_scratch, mask_scratch); |  3178   GetMarkBits(object, bitmap_scratch, mask_scratch); | 
|  3179  |  3179  | 
|  3180   Label other_color, word_boundary; |  3180   Label other_color, word_boundary; | 
|  3181   test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); |  3181   test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 
|  3182   j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear); |  3182   j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear); | 
|  3183   add(mask_scratch, mask_scratch);  // Shift left 1 by adding. |  3183   add(mask_scratch, mask_scratch);  // Shift left 1 by adding. | 
|  3184   j(zero, &word_boundary, Label::kNear); |  3184   j(zero, &word_boundary, Label::kNear); | 
|  3185   test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); |  3185   test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 
|  3186   j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance); |  3186   j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance); | 
|  3187   jmp(&other_color, Label::kNear); |  3187   jmp(&other_color, Label::kNear); | 
|  3188  |  3188  | 
|  3189   bind(&word_boundary); |  3189   bind(&word_boundary); | 
|  3190   test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize), 1); |  3190   test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize), 1); | 
|  3191  |  3191  | 
|  3192   j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance); |  3192   j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance); | 
|  3193   bind(&other_color); |  3193   bind(&other_color); | 
|  3194 } |  3194 } | 
|  3195  |  3195  | 
|  3196  |  3196  | 
|  3197 void MacroAssembler::GetMarkBits(Register addr_reg, |  3197 void MacroAssembler::GetMarkBits(Register addr_reg, | 
|  3198                                  Register bitmap_reg, |  3198                                  Register bitmap_reg, | 
|  3199                                  Register mask_reg) { |  3199                                  Register mask_reg) { | 
|  3200   ASSERT(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx)); |  3200   DCHECK(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx)); | 
|  3201   mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask)); |  3201   mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask)); | 
|  3202   and_(bitmap_reg, addr_reg); |  3202   and_(bitmap_reg, addr_reg); | 
|  3203   mov(ecx, addr_reg); |  3203   mov(ecx, addr_reg); | 
|  3204   int shift = |  3204   int shift = | 
|  3205       Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2; |  3205       Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2; | 
|  3206   shr(ecx, shift); |  3206   shr(ecx, shift); | 
|  3207   and_(ecx, |  3207   and_(ecx, | 
|  3208        (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1)); |  3208        (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1)); | 
|  3209  |  3209  | 
|  3210   add(bitmap_reg, ecx); |  3210   add(bitmap_reg, ecx); | 
|  3211   mov(ecx, addr_reg); |  3211   mov(ecx, addr_reg); | 
|  3212   shr(ecx, kPointerSizeLog2); |  3212   shr(ecx, kPointerSizeLog2); | 
|  3213   and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1); |  3213   and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1); | 
|  3214   mov(mask_reg, Immediate(1)); |  3214   mov(mask_reg, Immediate(1)); | 
|  3215   shl_cl(mask_reg); |  3215   shl_cl(mask_reg); | 
|  3216 } |  3216 } | 
|  3217  |  3217  | 
|  3218  |  3218  | 
|  3219 void MacroAssembler::EnsureNotWhite( |  3219 void MacroAssembler::EnsureNotWhite( | 
|  3220     Register value, |  3220     Register value, | 
|  3221     Register bitmap_scratch, |  3221     Register bitmap_scratch, | 
|  3222     Register mask_scratch, |  3222     Register mask_scratch, | 
|  3223     Label* value_is_white_and_not_data, |  3223     Label* value_is_white_and_not_data, | 
|  3224     Label::Distance distance) { |  3224     Label::Distance distance) { | 
|  3225   ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, ecx)); |  3225   DCHECK(!AreAliased(value, bitmap_scratch, mask_scratch, ecx)); | 
|  3226   GetMarkBits(value, bitmap_scratch, mask_scratch); |  3226   GetMarkBits(value, bitmap_scratch, mask_scratch); | 
|  3227  |  3227  | 
|  3228   // If the value is black or grey we don't need to do anything. |  3228   // If the value is black or grey we don't need to do anything. | 
|  3229   ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0); |  3229   DCHECK(strcmp(Marking::kWhiteBitPattern, "00") == 0); | 
|  3230   ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0); |  3230   DCHECK(strcmp(Marking::kBlackBitPattern, "10") == 0); | 
|  3231   ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0); |  3231   DCHECK(strcmp(Marking::kGreyBitPattern, "11") == 0); | 
|  3232   ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0); |  3232   DCHECK(strcmp(Marking::kImpossibleBitPattern, "01") == 0); | 
|  3233  |  3233  | 
|  3234   Label done; |  3234   Label done; | 
|  3235  |  3235  | 
|  3236   // Since both black and grey have a 1 in the first position and white does |  3236   // Since both black and grey have a 1 in the first position and white does | 
|  3237   // not have a 1 there we only need to check one bit. |  3237   // not have a 1 there we only need to check one bit. | 
|  3238   test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); |  3238   test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize)); | 
|  3239   j(not_zero, &done, Label::kNear); |  3239   j(not_zero, &done, Label::kNear); | 
|  3240  |  3240  | 
|  3241   if (emit_debug_code()) { |  3241   if (emit_debug_code()) { | 
|  3242     // Check for impossible bit pattern. |  3242     // Check for impossible bit pattern. | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
|  3260  |  3260  | 
|  3261   // Check for heap-number |  3261   // Check for heap-number | 
|  3262   mov(map, FieldOperand(value, HeapObject::kMapOffset)); |  3262   mov(map, FieldOperand(value, HeapObject::kMapOffset)); | 
|  3263   cmp(map, isolate()->factory()->heap_number_map()); |  3263   cmp(map, isolate()->factory()->heap_number_map()); | 
|  3264   j(not_equal, ¬_heap_number, Label::kNear); |  3264   j(not_equal, ¬_heap_number, Label::kNear); | 
|  3265   mov(length, Immediate(HeapNumber::kSize)); |  3265   mov(length, Immediate(HeapNumber::kSize)); | 
|  3266   jmp(&is_data_object, Label::kNear); |  3266   jmp(&is_data_object, Label::kNear); | 
|  3267  |  3267  | 
|  3268   bind(¬_heap_number); |  3268   bind(¬_heap_number); | 
|  3269   // Check for strings. |  3269   // Check for strings. | 
|  3270   ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); |  3270   DCHECK(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1); | 
|  3271   ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); |  3271   DCHECK(kNotStringTag == 0x80 && kIsNotStringMask == 0x80); | 
|  3272   // If it's a string and it's not a cons string then it's an object containing |  3272   // If it's a string and it's not a cons string then it's an object containing | 
|  3273   // no GC pointers. |  3273   // no GC pointers. | 
|  3274   Register instance_type = ecx; |  3274   Register instance_type = ecx; | 
|  3275   movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); |  3275   movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset)); | 
|  3276   test_b(instance_type, kIsIndirectStringMask | kIsNotStringMask); |  3276   test_b(instance_type, kIsIndirectStringMask | kIsNotStringMask); | 
|  3277   j(not_zero, value_is_white_and_not_data); |  3277   j(not_zero, value_is_white_and_not_data); | 
|  3278   // It's a non-indirect (non-cons and non-slice) string. |  3278   // It's a non-indirect (non-cons and non-slice) string. | 
|  3279   // If it's external, the length is just ExternalString::kSize. |  3279   // If it's external, the length is just ExternalString::kSize. | 
|  3280   // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). |  3280   // Otherwise it's String::kHeaderSize + string->length() * (1 or 2). | 
|  3281   Label not_external; |  3281   Label not_external; | 
|  3282   // External strings are the only ones with the kExternalStringTag bit |  3282   // External strings are the only ones with the kExternalStringTag bit | 
|  3283   // set. |  3283   // set. | 
|  3284   ASSERT_EQ(0, kSeqStringTag & kExternalStringTag); |  3284   DCHECK_EQ(0, kSeqStringTag & kExternalStringTag); | 
|  3285   ASSERT_EQ(0, kConsStringTag & kExternalStringTag); |  3285   DCHECK_EQ(0, kConsStringTag & kExternalStringTag); | 
|  3286   test_b(instance_type, kExternalStringTag); |  3286   test_b(instance_type, kExternalStringTag); | 
|  3287   j(zero, ¬_external, Label::kNear); |  3287   j(zero, ¬_external, Label::kNear); | 
|  3288   mov(length, Immediate(ExternalString::kSize)); |  3288   mov(length, Immediate(ExternalString::kSize)); | 
|  3289   jmp(&is_data_object, Label::kNear); |  3289   jmp(&is_data_object, Label::kNear); | 
|  3290  |  3290  | 
|  3291   bind(¬_external); |  3291   bind(¬_external); | 
|  3292   // Sequential string, either ASCII or UC16. |  3292   // Sequential string, either ASCII or UC16. | 
|  3293   ASSERT(kOneByteStringTag == 0x04); |  3293   DCHECK(kOneByteStringTag == 0x04); | 
|  3294   and_(length, Immediate(kStringEncodingMask)); |  3294   and_(length, Immediate(kStringEncodingMask)); | 
|  3295   xor_(length, Immediate(kStringEncodingMask)); |  3295   xor_(length, Immediate(kStringEncodingMask)); | 
|  3296   add(length, Immediate(0x04)); |  3296   add(length, Immediate(0x04)); | 
|  3297   // Value now either 4 (if ASCII) or 8 (if UC16), i.e., char-size shifted |  3297   // Value now either 4 (if ASCII) or 8 (if UC16), i.e., char-size shifted | 
|  3298   // by 2. If we multiply the string length as smi by this, it still |  3298   // by 2. If we multiply the string length as smi by this, it still | 
|  3299   // won't overflow a 32-bit value. |  3299   // won't overflow a 32-bit value. | 
|  3300   ASSERT_EQ(SeqOneByteString::kMaxSize, SeqTwoByteString::kMaxSize); |  3300   DCHECK_EQ(SeqOneByteString::kMaxSize, SeqTwoByteString::kMaxSize); | 
|  3301   ASSERT(SeqOneByteString::kMaxSize <= |  3301   DCHECK(SeqOneByteString::kMaxSize <= | 
|  3302          static_cast<int>(0xffffffffu >> (2 + kSmiTagSize))); |  3302          static_cast<int>(0xffffffffu >> (2 + kSmiTagSize))); | 
|  3303   imul(length, FieldOperand(value, String::kLengthOffset)); |  3303   imul(length, FieldOperand(value, String::kLengthOffset)); | 
|  3304   shr(length, 2 + kSmiTagSize + kSmiShiftSize); |  3304   shr(length, 2 + kSmiTagSize + kSmiShiftSize); | 
|  3305   add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); |  3305   add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask)); | 
|  3306   and_(length, Immediate(~kObjectAlignmentMask)); |  3306   and_(length, Immediate(~kObjectAlignmentMask)); | 
|  3307  |  3307  | 
|  3308   bind(&is_data_object); |  3308   bind(&is_data_object); | 
|  3309   // Value is a data object, and it is white.  Mark it black.  Since we know |  3309   // Value is a data object, and it is white.  Mark it black.  Since we know | 
|  3310   // that the object is white we can make it black by flipping one bit. |  3310   // that the object is white we can make it black by flipping one bit. | 
|  3311   or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); |  3311   or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch); | 
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3391   cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), |  3391   cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), | 
|  3392       Immediate(isolate()->factory()->allocation_memento_map())); |  3392       Immediate(isolate()->factory()->allocation_memento_map())); | 
|  3393 } |  3393 } | 
|  3394  |  3394  | 
|  3395  |  3395  | 
|  3396 void MacroAssembler::JumpIfDictionaryInPrototypeChain( |  3396 void MacroAssembler::JumpIfDictionaryInPrototypeChain( | 
|  3397     Register object, |  3397     Register object, | 
|  3398     Register scratch0, |  3398     Register scratch0, | 
|  3399     Register scratch1, |  3399     Register scratch1, | 
|  3400     Label* found) { |  3400     Label* found) { | 
|  3401   ASSERT(!scratch1.is(scratch0)); |  3401   DCHECK(!scratch1.is(scratch0)); | 
|  3402   Factory* factory = isolate()->factory(); |  3402   Factory* factory = isolate()->factory(); | 
|  3403   Register current = scratch0; |  3403   Register current = scratch0; | 
|  3404   Label loop_again; |  3404   Label loop_again; | 
|  3405  |  3405  | 
|  3406   // scratch contained elements pointer. |  3406   // scratch contained elements pointer. | 
|  3407   mov(current, object); |  3407   mov(current, object); | 
|  3408  |  3408  | 
|  3409   // Loop based on the map going up the prototype chain. |  3409   // Loop based on the map going up the prototype chain. | 
|  3410   bind(&loop_again); |  3410   bind(&loop_again); | 
|  3411   mov(current, FieldOperand(current, HeapObject::kMapOffset)); |  3411   mov(current, FieldOperand(current, HeapObject::kMapOffset)); | 
|  3412   mov(scratch1, FieldOperand(current, Map::kBitField2Offset)); |  3412   mov(scratch1, FieldOperand(current, Map::kBitField2Offset)); | 
|  3413   DecodeField<Map::ElementsKindBits>(scratch1); |  3413   DecodeField<Map::ElementsKindBits>(scratch1); | 
|  3414   cmp(scratch1, Immediate(DICTIONARY_ELEMENTS)); |  3414   cmp(scratch1, Immediate(DICTIONARY_ELEMENTS)); | 
|  3415   j(equal, found); |  3415   j(equal, found); | 
|  3416   mov(current, FieldOperand(current, Map::kPrototypeOffset)); |  3416   mov(current, FieldOperand(current, Map::kPrototypeOffset)); | 
|  3417   cmp(current, Immediate(factory->null_value())); |  3417   cmp(current, Immediate(factory->null_value())); | 
|  3418   j(not_equal, &loop_again); |  3418   j(not_equal, &loop_again); | 
|  3419 } |  3419 } | 
|  3420  |  3420  | 
|  3421  |  3421  | 
|  3422 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) { |  3422 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) { | 
|  3423   ASSERT(!dividend.is(eax)); |  3423   DCHECK(!dividend.is(eax)); | 
|  3424   ASSERT(!dividend.is(edx)); |  3424   DCHECK(!dividend.is(edx)); | 
|  3425   MultiplierAndShift ms(divisor); |  3425   MultiplierAndShift ms(divisor); | 
|  3426   mov(eax, Immediate(ms.multiplier())); |  3426   mov(eax, Immediate(ms.multiplier())); | 
|  3427   imul(dividend); |  3427   imul(dividend); | 
|  3428   if (divisor > 0 && ms.multiplier() < 0) add(edx, dividend); |  3428   if (divisor > 0 && ms.multiplier() < 0) add(edx, dividend); | 
|  3429   if (divisor < 0 && ms.multiplier() > 0) sub(edx, dividend); |  3429   if (divisor < 0 && ms.multiplier() > 0) sub(edx, dividend); | 
|  3430   if (ms.shift() > 0) sar(edx, ms.shift()); |  3430   if (ms.shift() > 0) sar(edx, ms.shift()); | 
|  3431   mov(eax, dividend); |  3431   mov(eax, dividend); | 
|  3432   shr(eax, 31); |  3432   shr(eax, 31); | 
|  3433   add(edx, eax); |  3433   add(edx, eax); | 
|  3434 } |  3434 } | 
|  3435  |  3435  | 
|  3436  |  3436  | 
|  3437 } }  // namespace v8::internal |  3437 } }  // namespace v8::internal | 
|  3438  |  3438  | 
|  3439 #endif  // V8_TARGET_ARCH_IA32 |  3439 #endif  // V8_TARGET_ARCH_IA32 | 
| OLD | NEW |