| 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 |