summaryrefslogtreecommitdiff
path: root/deps/v8/src/ia32/macro-assembler-ia32.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/ia32/macro-assembler-ia32.cc')
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.cc737
1 files changed, 155 insertions, 582 deletions
diff --git a/deps/v8/src/ia32/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc
index 3aaa22acc..837112a55 100644
--- a/deps/v8/src/ia32/macro-assembler-ia32.cc
+++ b/deps/v8/src/ia32/macro-assembler-ia32.cc
@@ -44,8 +44,7 @@ namespace internal {
MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
: Assembler(arg_isolate, buffer, size),
generating_stub_(false),
- allow_stub_calls_(true),
- has_frame_(false) {
+ allow_stub_calls_(true) {
if (isolate() != NULL) {
code_object_ = Handle<Object>(isolate()->heap()->undefined_value(),
isolate());
@@ -53,75 +52,33 @@ MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size)
}
-void MacroAssembler::InNewSpace(
- Register object,
- Register scratch,
- Condition cc,
- Label* condition_met,
- Label::Distance condition_met_distance) {
- ASSERT(cc == equal || cc == not_equal);
- if (scratch.is(object)) {
- and_(scratch, Immediate(~Page::kPageAlignmentMask));
- } else {
- mov(scratch, Immediate(~Page::kPageAlignmentMask));
- and_(scratch, object);
+void MacroAssembler::RecordWriteHelper(Register object,
+ Register addr,
+ Register scratch) {
+ if (emit_debug_code()) {
+ // Check that the object is not in new space.
+ Label not_in_new_space;
+ InNewSpace(object, scratch, not_equal, &not_in_new_space);
+ Abort("new-space object passed to RecordWriteHelper");
+ bind(&not_in_new_space);
}
- // Check that we can use a test_b.
- ASSERT(MemoryChunk::IN_FROM_SPACE < 8);
- ASSERT(MemoryChunk::IN_TO_SPACE < 8);
- int mask = (1 << MemoryChunk::IN_FROM_SPACE)
- | (1 << MemoryChunk::IN_TO_SPACE);
- // If non-zero, the page belongs to new-space.
- test_b(Operand(scratch, MemoryChunk::kFlagsOffset),
- static_cast<uint8_t>(mask));
- j(cc, condition_met, condition_met_distance);
-}
+ // Compute the page start address from the heap object pointer, and reuse
+ // the 'object' register for it.
+ and_(object, ~Page::kPageAlignmentMask);
-void MacroAssembler::RememberedSetHelper(
- Register object, // Only used for debug checks.
- Register addr,
- Register scratch,
- SaveFPRegsMode save_fp,
- MacroAssembler::RememberedSetFinalAction and_then) {
- Label done;
- if (FLAG_debug_code) {
- Label ok;
- JumpIfNotInNewSpace(object, scratch, &ok, Label::kNear);
- int3();
- bind(&ok);
- }
- // Load store buffer top.
- ExternalReference store_buffer =
- ExternalReference::store_buffer_top(isolate());
- mov(scratch, Operand::StaticVariable(store_buffer));
- // Store pointer to buffer.
- mov(Operand(scratch, 0), addr);
- // Increment buffer top.
- add(scratch, Immediate(kPointerSize));
- // Write back new top of buffer.
- mov(Operand::StaticVariable(store_buffer), scratch);
- // Call stub on end of buffer.
- // Check for end of buffer.
- test(scratch, Immediate(StoreBuffer::kStoreBufferOverflowBit));
- if (and_then == kReturnAtEnd) {
- Label buffer_overflowed;
- j(not_equal, &buffer_overflowed, Label::kNear);
- ret(0);
- bind(&buffer_overflowed);
- } else {
- ASSERT(and_then == kFallThroughAtEnd);
- j(equal, &done, Label::kNear);
- }
- StoreBufferOverflowStub store_buffer_overflow =
- StoreBufferOverflowStub(save_fp);
- CallStub(&store_buffer_overflow);
- if (and_then == kReturnAtEnd) {
- ret(0);
- } else {
- ASSERT(and_then == kFallThroughAtEnd);
- bind(&done);
- }
+ // Compute number of region covering addr. See Page::GetRegionNumberForAddress
+ // method for more details.
+ shr(addr, Page::kRegionSizeLog2);
+ and_(addr, Page::kPageAlignmentMask >> Page::kRegionSizeLog2);
+
+ // Set dirty mark for region.
+ // Bit tests with a memory operand should be avoided on Intel processors,
+ // as they usually have long latency and multiple uops. We load the bit base
+ // operand to a register at first and store it back after bit set.
+ mov(scratch, Operand(object, Page::kDirtyFlagOffset));
+ bts(Operand(scratch), addr);
+ mov(Operand(object, Page::kDirtyFlagOffset), scratch);
}
@@ -155,144 +112,100 @@ void MacroAssembler::ClampUint8(Register reg) {
}
-void MacroAssembler::RecordWriteArray(Register object,
- Register value,
- Register index,
- SaveFPRegsMode save_fp,
- RememberedSetAction remembered_set_action,
- SmiCheck smi_check) {
- // First, check if a write barrier is even needed. The tests below
- // catch stores of Smis.
- Label done;
-
- // Skip barrier if writing a smi.
- if (smi_check == INLINE_SMI_CHECK) {
- ASSERT_EQ(0, kSmiTag);
- test(value, Immediate(kSmiTagMask));
- j(zero, &done);
- }
-
- // Array access: calculate the destination address in the same manner as
- // KeyedStoreIC::GenerateGeneric. Multiply a smi by 2 to get an offset
- // into an array of words.
- Register dst = index;
- lea(dst, Operand(object, index, times_half_pointer_size,
- FixedArray::kHeaderSize - kHeapObjectTag));
-
- RecordWrite(
- object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
-
- bind(&done);
-
- // Clobber clobbered input registers when running with the debug-code flag
- // turned on to provoke errors.
- if (emit_debug_code()) {
- mov(value, Immediate(BitCast<int32_t>(kZapValue)));
- mov(index, Immediate(BitCast<int32_t>(kZapValue)));
+void MacroAssembler::InNewSpace(Register object,
+ Register scratch,
+ Condition cc,
+ Label* branch,
+ Label::Distance branch_near) {
+ ASSERT(cc == equal || cc == not_equal);
+ if (Serializer::enabled()) {
+ // Can't do arithmetic on external references if it might get serialized.
+ mov(scratch, Operand(object));
+ // The mask isn't really an address. We load it as an external reference in
+ // case the size of the new space is different between the snapshot maker
+ // and the running system.
+ and_(Operand(scratch),
+ Immediate(ExternalReference::new_space_mask(isolate())));
+ cmp(Operand(scratch),
+ Immediate(ExternalReference::new_space_start(isolate())));
+ j(cc, branch, branch_near);
+ } else {
+ int32_t new_space_start = reinterpret_cast<int32_t>(
+ ExternalReference::new_space_start(isolate()).address());
+ lea(scratch, Operand(object, -new_space_start));
+ and_(scratch, isolate()->heap()->NewSpaceMask());
+ j(cc, branch, branch_near);
}
}
-void MacroAssembler::RecordWriteField(
- Register object,
- int offset,
- Register value,
- Register dst,
- SaveFPRegsMode save_fp,
- RememberedSetAction remembered_set_action,
- SmiCheck smi_check) {
+void MacroAssembler::RecordWrite(Register object,
+ int offset,
+ Register value,
+ Register scratch) {
// First, check if a write barrier is even needed. The tests below
- // catch stores of Smis.
+ // catch stores of Smis and stores into young gen.
Label done;
// Skip barrier if writing a smi.
- if (smi_check == INLINE_SMI_CHECK) {
- JumpIfSmi(value, &done, Label::kNear);
- }
+ STATIC_ASSERT(kSmiTag == 0);
+ JumpIfSmi(value, &done, Label::kNear);
- // Although the object register is tagged, the offset is relative to the start
- // of the object, so so offset must be a multiple of kPointerSize.
- ASSERT(IsAligned(offset, kPointerSize));
+ InNewSpace(object, value, equal, &done, Label::kNear);
- lea(dst, FieldOperand(object, offset));
- if (emit_debug_code()) {
- Label ok;
- test_b(dst, (1 << kPointerSizeLog2) - 1);
- j(zero, &ok, Label::kNear);
- int3();
- bind(&ok);
- }
+ // The offset is relative to a tagged or untagged HeapObject pointer,
+ // so either offset or offset + kHeapObjectTag must be a
+ // multiple of kPointerSize.
+ ASSERT(IsAligned(offset, kPointerSize) ||
+ IsAligned(offset + kHeapObjectTag, kPointerSize));
- RecordWrite(
- object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
+ Register dst = scratch;
+ if (offset != 0) {
+ lea(dst, Operand(object, offset));
+ } else {
+ // Array access: calculate the destination address in the same manner as
+ // KeyedStoreIC::GenerateGeneric. Multiply a smi by 2 to get an offset
+ // into an array of words.
+ STATIC_ASSERT(kSmiTagSize == 1);
+ STATIC_ASSERT(kSmiTag == 0);
+ lea(dst, Operand(object, dst, times_half_pointer_size,
+ FixedArray::kHeaderSize - kHeapObjectTag));
+ }
+ RecordWriteHelper(object, dst, value);
bind(&done);
- // Clobber clobbered input registers when running with the debug-code flag
+ // Clobber all input registers when running with the debug-code flag
// turned on to provoke errors.
if (emit_debug_code()) {
+ mov(object, Immediate(BitCast<int32_t>(kZapValue)));
mov(value, Immediate(BitCast<int32_t>(kZapValue)));
- mov(dst, Immediate(BitCast<int32_t>(kZapValue)));
+ mov(scratch, Immediate(BitCast<int32_t>(kZapValue)));
}
}
void MacroAssembler::RecordWrite(Register object,
Register address,
- Register value,
- SaveFPRegsMode fp_mode,
- RememberedSetAction remembered_set_action,
- SmiCheck smi_check) {
- ASSERT(!object.is(value));
- ASSERT(!object.is(address));
- ASSERT(!value.is(address));
- if (emit_debug_code()) {
- AbortIfSmi(object);
- }
-
- if (remembered_set_action == OMIT_REMEMBERED_SET &&
- !FLAG_incremental_marking) {
- return;
- }
-
- if (FLAG_debug_code) {
- Label ok;
- cmp(value, Operand(address, 0));
- j(equal, &ok, Label::kNear);
- int3();
- bind(&ok);
- }
-
+ Register value) {
// First, check if a write barrier is even needed. The tests below
// catch stores of Smis and stores into young gen.
Label done;
- if (smi_check == INLINE_SMI_CHECK) {
- // Skip barrier if writing a smi.
- JumpIfSmi(value, &done, Label::kNear);
- }
-
- CheckPageFlag(value,
- value, // Used as scratch.
- MemoryChunk::kPointersToHereAreInterestingMask,
- zero,
- &done,
- Label::kNear);
- CheckPageFlag(object,
- value, // Used as scratch.
- MemoryChunk::kPointersFromHereAreInterestingMask,
- zero,
- &done,
- Label::kNear);
-
- RecordWriteStub stub(object, value, address, remembered_set_action, fp_mode);
- CallStub(&stub);
+ // Skip barrier if writing a smi.
+ STATIC_ASSERT(kSmiTag == 0);
+ JumpIfSmi(value, &done, Label::kNear);
+
+ InNewSpace(object, value, equal, &done);
+
+ RecordWriteHelper(object, address, value);
bind(&done);
- // Clobber clobbered registers when running with the debug-code flag
+ // Clobber all input registers when running with the debug-code flag
// turned on to provoke errors.
if (emit_debug_code()) {
+ mov(object, Immediate(BitCast<int32_t>(kZapValue)));
mov(address, Immediate(BitCast<int32_t>(kZapValue)));
mov(value, Immediate(BitCast<int32_t>(kZapValue)));
}
@@ -311,7 +224,7 @@ void MacroAssembler::DebugBreak() {
void MacroAssembler::Set(Register dst, const Immediate& x) {
if (x.is_zero()) {
- xor_(dst, dst); // Shorter than mov.
+ xor_(dst, Operand(dst)); // Shorter than mov.
} else {
mov(dst, x);
}
@@ -374,111 +287,13 @@ void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
void MacroAssembler::CheckFastElements(Register map,
Label* fail,
Label::Distance distance) {
- STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
- STATIC_ASSERT(FAST_ELEMENTS == 1);
- cmpb(FieldOperand(map, Map::kBitField2Offset),
- Map::kMaximumBitField2FastElementValue);
- j(above, fail, distance);
-}
-
-
-void MacroAssembler::CheckFastObjectElements(Register map,
- Label* fail,
- Label::Distance distance) {
- STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
- STATIC_ASSERT(FAST_ELEMENTS == 1);
- cmpb(FieldOperand(map, Map::kBitField2Offset),
- Map::kMaximumBitField2FastSmiOnlyElementValue);
- j(below_equal, fail, distance);
+ STATIC_ASSERT(FAST_ELEMENTS == 0);
cmpb(FieldOperand(map, Map::kBitField2Offset),
Map::kMaximumBitField2FastElementValue);
j(above, fail, distance);
}
-void MacroAssembler::CheckFastSmiOnlyElements(Register map,
- Label* fail,
- Label::Distance distance) {
- STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
- cmpb(FieldOperand(map, Map::kBitField2Offset),
- Map::kMaximumBitField2FastSmiOnlyElementValue);
- j(above, fail, distance);
-}
-
-
-void MacroAssembler::StoreNumberToDoubleElements(
- Register maybe_number,
- Register elements,
- Register key,
- Register scratch1,
- XMMRegister scratch2,
- Label* fail,
- bool specialize_for_processor) {
- Label smi_value, done, maybe_nan, not_nan, is_nan, have_double_value;
- JumpIfSmi(maybe_number, &smi_value, Label::kNear);
-
- CheckMap(maybe_number,
- isolate()->factory()->heap_number_map(),
- fail,
- DONT_DO_SMI_CHECK);
-
- // Double value, canonicalize NaN.
- uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
- cmp(FieldOperand(maybe_number, offset),
- Immediate(kNaNOrInfinityLowerBoundUpper32));
- j(greater_equal, &maybe_nan, Label::kNear);
-
- bind(&not_nan);
- ExternalReference canonical_nan_reference =
- ExternalReference::address_of_canonical_non_hole_nan();
- if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
- CpuFeatures::Scope use_sse2(SSE2);
- movdbl(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset));
- bind(&have_double_value);
- movdbl(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize),
- scratch2);
- } else {
- fld_d(FieldOperand(maybe_number, HeapNumber::kValueOffset));
- bind(&have_double_value);
- fstp_d(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize));
- }
- jmp(&done);
-
- bind(&maybe_nan);
- // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
- // it's an Infinity, and the non-NaN code path applies.
- j(greater, &is_nan, Label::kNear);
- cmp(FieldOperand(maybe_number, HeapNumber::kValueOffset), Immediate(0));
- j(zero, &not_nan);
- bind(&is_nan);
- if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
- CpuFeatures::Scope use_sse2(SSE2);
- movdbl(scratch2, Operand::StaticVariable(canonical_nan_reference));
- } else {
- fld_d(Operand::StaticVariable(canonical_nan_reference));
- }
- jmp(&have_double_value, Label::kNear);
-
- bind(&smi_value);
- // Value is a smi. Convert to a double and store.
- // Preserve original value.
- mov(scratch1, maybe_number);
- SmiUntag(scratch1);
- if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
- CpuFeatures::Scope fscope(SSE2);
- cvtsi2sd(scratch2, scratch1);
- movdbl(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize),
- scratch2);
- } else {
- push(scratch1);
- fild_s(Operand(esp, 0));
- pop(scratch1);
- fstp_d(FieldOperand(elements, key, times_4, FixedDoubleArray::kHeaderSize));
- }
- bind(&done);
-}
-
-
void MacroAssembler::CheckMap(Register obj,
Handle<Map> map,
Label* fail,
@@ -530,7 +345,7 @@ void MacroAssembler::IsInstanceJSObjectType(Register map,
Register scratch,
Label* fail) {
movzx_b(scratch, FieldOperand(map, Map::kInstanceTypeOffset));
- sub(scratch, Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
+ sub(Operand(scratch), Immediate(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE));
cmp(scratch,
LAST_NONCALLABLE_SPEC_OBJECT_TYPE - FIRST_NONCALLABLE_SPEC_OBJECT_TYPE);
j(above, fail);
@@ -587,7 +402,7 @@ void MacroAssembler::AbortIfSmi(Register object) {
void MacroAssembler::EnterFrame(StackFrame::Type type) {
push(ebp);
- mov(ebp, esp);
+ mov(ebp, Operand(esp));
push(esi);
push(Immediate(Smi::FromInt(type)));
push(Immediate(CodeObject()));
@@ -614,7 +429,7 @@ void MacroAssembler::EnterExitFramePrologue() {
ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
ASSERT(ExitFrameConstants::kCallerFPOffset == 0 * kPointerSize);
push(ebp);
- mov(ebp, esp);
+ mov(ebp, Operand(esp));
// Reserve room for entry stack pointer and push the code object.
ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
@@ -636,14 +451,14 @@ void MacroAssembler::EnterExitFrameEpilogue(int argc, bool save_doubles) {
if (save_doubles) {
CpuFeatures::Scope scope(SSE2);
int space = XMMRegister::kNumRegisters * kDoubleSize + argc * kPointerSize;
- sub(esp, Immediate(space));
+ sub(Operand(esp), Immediate(space));
const int offset = -2 * kPointerSize;
for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
XMMRegister reg = XMMRegister::from_code(i);
movdbl(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg);
}
} else {
- sub(esp, Immediate(argc * kPointerSize));
+ sub(Operand(esp), Immediate(argc * kPointerSize));
}
// Get the required frame alignment for the OS.
@@ -663,7 +478,7 @@ void MacroAssembler::EnterExitFrame(bool save_doubles) {
// Setup argc and argv in callee-saved registers.
int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
- mov(edi, eax);
+ mov(edi, Operand(eax));
lea(esi, Operand(ebp, eax, times_4, offset));
// Reserve space for argc, argv and isolate.
@@ -717,7 +532,7 @@ void MacroAssembler::LeaveExitFrameEpilogue() {
void MacroAssembler::LeaveApiExitFrame() {
- mov(esp, ebp);
+ mov(esp, Operand(ebp));
pop(ebp);
LeaveExitFrameEpilogue();
@@ -765,7 +580,7 @@ void MacroAssembler::PopTryHandler() {
STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
pop(Operand::StaticVariable(ExternalReference(Isolate::kHandlerAddress,
isolate())));
- add(esp, Immediate(StackHandlerConstants::kSize - kPointerSize));
+ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize));
}
@@ -797,7 +612,7 @@ void MacroAssembler::Throw(Register value) {
// (edx == ENTRY) == (ebp == 0) == (esi == 0), so we could test any
// of them.
Label skip;
- cmp(edx, Immediate(StackHandler::ENTRY));
+ cmp(Operand(edx), Immediate(StackHandler::ENTRY));
j(equal, &skip, Label::kNear);
mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi);
bind(&skip);
@@ -881,7 +696,7 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
// When generating debug code, make sure the lexical context is set.
if (emit_debug_code()) {
- cmp(scratch, Immediate(0));
+ cmp(Operand(scratch), Immediate(0));
Check(not_equal, "we should not have an empty lexical context");
}
// Load the global context of the current context.
@@ -969,23 +784,23 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss,
mov(r1, r0);
not_(r0);
shl(r1, 15);
- add(r0, r1);
+ add(r0, Operand(r1));
// hash = hash ^ (hash >> 12);
mov(r1, r0);
shr(r1, 12);
- xor_(r0, r1);
+ xor_(r0, Operand(r1));
// hash = hash + (hash << 2);
lea(r0, Operand(r0, r0, times_4, 0));
// hash = hash ^ (hash >> 4);
mov(r1, r0);
shr(r1, 4);
- xor_(r0, r1);
+ xor_(r0, Operand(r1));
// hash = hash * 2057;
imul(r0, r0, 2057);
// hash = hash ^ (hash >> 16);
mov(r1, r0);
shr(r1, 16);
- xor_(r0, r1);
+ xor_(r0, Operand(r1));
// Compute capacity mask.
mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset));
@@ -999,9 +814,9 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss,
mov(r2, r0);
// Compute the masked index: (hash + i + i * i) & mask.
if (i > 0) {
- add(r2, Immediate(NumberDictionary::GetProbeOffset(i)));
+ add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i)));
}
- and_(r2, r1);
+ and_(r2, Operand(r1));
// Scale the index by multiplying by the entry size.
ASSERT(NumberDictionary::kEntrySize == 3);
@@ -1057,7 +872,7 @@ void MacroAssembler::LoadAllocationTopHelper(Register result,
if (scratch.is(no_reg)) {
mov(result, Operand::StaticVariable(new_space_allocation_top));
} else {
- mov(scratch, Immediate(new_space_allocation_top));
+ mov(Operand(scratch), Immediate(new_space_allocation_top));
mov(result, Operand(scratch, 0));
}
}
@@ -1116,7 +931,7 @@ void MacroAssembler::AllocateInNewSpace(int object_size,
if (!top_reg.is(result)) {
mov(top_reg, result);
}
- add(top_reg, Immediate(object_size));
+ add(Operand(top_reg), Immediate(object_size));
j(carry, gc_required);
cmp(top_reg, Operand::StaticVariable(new_space_allocation_limit));
j(above, gc_required);
@@ -1127,12 +942,12 @@ void MacroAssembler::AllocateInNewSpace(int object_size,
// Tag result if requested.
if (top_reg.is(result)) {
if ((flags & TAG_OBJECT) != 0) {
- sub(result, Immediate(object_size - kHeapObjectTag));
+ sub(Operand(result), Immediate(object_size - kHeapObjectTag));
} else {
- sub(result, Immediate(object_size));
+ sub(Operand(result), Immediate(object_size));
}
} else if ((flags & TAG_OBJECT) != 0) {
- add(result, Immediate(kHeapObjectTag));
+ add(Operand(result), Immediate(kHeapObjectTag));
}
}
@@ -1170,7 +985,7 @@ void MacroAssembler::AllocateInNewSpace(int header_size,
// We assume that element_count*element_size + header_size does not
// overflow.
lea(result_end, Operand(element_count, element_size, header_size));
- add(result_end, result);
+ add(result_end, Operand(result));
j(carry, gc_required);
cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
j(above, gc_required);
@@ -1215,7 +1030,7 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
if (!object_size.is(result_end)) {
mov(result_end, object_size);
}
- add(result_end, result);
+ add(result_end, Operand(result));
j(carry, gc_required);
cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
j(above, gc_required);
@@ -1235,7 +1050,7 @@ void MacroAssembler::UndoAllocationInNewSpace(Register object) {
ExternalReference::new_space_allocation_top_address(isolate());
// Make sure the object has no tag before resetting top.
- and_(object, Immediate(~kHeapObjectTagMask));
+ and_(Operand(object), Immediate(~kHeapObjectTagMask));
#ifdef DEBUG
cmp(object, Operand::StaticVariable(new_space_allocation_top));
Check(below, "Undo allocation of non allocated memory");
@@ -1274,7 +1089,7 @@ void MacroAssembler::AllocateTwoByteString(Register result,
ASSERT(kShortSize == 2);
// scratch1 = length * 2 + kObjectAlignmentMask.
lea(scratch1, Operand(length, length, times_1, kObjectAlignmentMask));
- and_(scratch1, Immediate(~kObjectAlignmentMask));
+ and_(Operand(scratch1), Immediate(~kObjectAlignmentMask));
// Allocate two byte string in new space.
AllocateInNewSpace(SeqTwoByteString::kHeaderSize,
@@ -1308,8 +1123,8 @@ void MacroAssembler::AllocateAsciiString(Register result,
ASSERT((SeqAsciiString::kHeaderSize & kObjectAlignmentMask) == 0);
mov(scratch1, length);
ASSERT(kCharSize == 1);
- add(scratch1, Immediate(kObjectAlignmentMask));
- and_(scratch1, Immediate(~kObjectAlignmentMask));
+ add(Operand(scratch1), Immediate(kObjectAlignmentMask));
+ and_(Operand(scratch1), Immediate(~kObjectAlignmentMask));
// Allocate ascii string in new space.
AllocateInNewSpace(SeqAsciiString::kHeaderSize,
@@ -1443,7 +1258,7 @@ void MacroAssembler::CopyBytes(Register source,
Register scratch) {
Label loop, done, short_string, short_loop;
// Experimentation shows that the short string loop is faster if length < 10.
- cmp(length, Immediate(10));
+ cmp(Operand(length), Immediate(10));
j(less_equal, &short_string);
ASSERT(source.is(esi));
@@ -1458,12 +1273,12 @@ void MacroAssembler::CopyBytes(Register source,
mov(scratch, ecx);
shr(ecx, 2);
rep_movs();
- and_(scratch, Immediate(0x3));
- add(destination, scratch);
+ and_(Operand(scratch), Immediate(0x3));
+ add(destination, Operand(scratch));
jmp(&done);
bind(&short_string);
- test(length, length);
+ test(length, Operand(length));
j(zero, &done);
bind(&short_loop);
@@ -1478,27 +1293,13 @@ void MacroAssembler::CopyBytes(Register source,
}
-void MacroAssembler::InitializeFieldsWithFiller(Register start_offset,
- Register end_offset,
- Register filler) {
- Label loop, entry;
- jmp(&entry);
- bind(&loop);
- mov(Operand(start_offset, 0), filler);
- add(start_offset, Immediate(kPointerSize));
- bind(&entry);
- cmp(start_offset, end_offset);
- j(less, &loop);
-}
-
-
void MacroAssembler::NegativeZeroTest(Register result,
Register op,
Label* then_label) {
Label ok;
- test(result, result);
+ test(result, Operand(result));
j(not_zero, &ok);
- test(op, op);
+ test(op, Operand(op));
j(sign, then_label);
bind(&ok);
}
@@ -1510,10 +1311,10 @@ void MacroAssembler::NegativeZeroTest(Register result,
Register scratch,
Label* then_label) {
Label ok;
- test(result, result);
+ test(result, Operand(result));
j(not_zero, &ok);
- mov(scratch, op1);
- or_(scratch, op2);
+ mov(scratch, Operand(op1));
+ or_(scratch, Operand(op2));
j(sign, then_label);
bind(&ok);
}
@@ -1543,7 +1344,7 @@ void MacroAssembler::TryGetFunctionPrototype(Register function,
// If the prototype or initial map is the hole, don't return it and
// simply miss the cache instead. This will allow us to allocate a
// prototype object on-demand in the runtime system.
- cmp(result, Immediate(isolate()->factory()->the_hole_value()));
+ cmp(Operand(result), Immediate(isolate()->factory()->the_hole_value()));
j(equal, miss);
// If the function does not have an initial map, we're done.
@@ -1566,13 +1367,13 @@ void MacroAssembler::TryGetFunctionPrototype(Register function,
void MacroAssembler::CallStub(CodeStub* stub, unsigned ast_id) {
- ASSERT(AllowThisStubCall(stub)); // Calls are not allowed in some stubs.
+ ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id);
}
MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub) {
- ASSERT(AllowThisStubCall(stub)); // Calls are not allowed in some stubs.
+ ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
Object* result;
{ MaybeObject* maybe_result = stub->TryGetCode();
if (!maybe_result->ToObject(&result)) return maybe_result;
@@ -1583,12 +1384,13 @@ MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub) {
void MacroAssembler::TailCallStub(CodeStub* stub) {
- ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe());
+ ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
jmp(stub->GetCode(), RelocInfo::CODE_TARGET);
}
MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub) {
+ ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
Object* result;
{ MaybeObject* maybe_result = stub->TryGetCode();
if (!maybe_result->ToObject(&result)) return maybe_result;
@@ -1604,15 +1406,9 @@ void MacroAssembler::StubReturn(int argc) {
}
-bool MacroAssembler::AllowThisStubCall(CodeStub* stub) {
- if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false;
- return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe();
-}
-
-
void MacroAssembler::IllegalOperation(int num_arguments) {
if (num_arguments > 0) {
- add(esp, Immediate(num_arguments * kPointerSize));
+ add(Operand(esp), Immediate(num_arguments * kPointerSize));
}
mov(eax, Immediate(isolate()->factory()->undefined_value()));
}
@@ -1646,7 +1442,8 @@ void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
const Runtime::Function* function = Runtime::FunctionForId(id);
Set(eax, Immediate(function->nargs));
mov(ebx, Immediate(ExternalReference(function, isolate())));
- CEntryStub ces(1, kSaveFPRegs);
+ CEntryStub ces(1);
+ ces.SaveDoubles();
CallStub(&ces);
}
@@ -1826,7 +1623,7 @@ MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
Label leave_exit_frame;
// Check if the result handle holds 0.
- test(eax, eax);
+ test(eax, Operand(eax));
j(zero, &empty_handle);
// It was non-zero. Dereference to get the result value.
mov(eax, Operand(eax, 0));
@@ -1867,7 +1664,7 @@ MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
mov(edi, eax);
mov(Operand(esp, 0), Immediate(ExternalReference::isolate_address()));
mov(eax, Immediate(delete_extensions));
- call(eax);
+ call(Operand(eax));
mov(eax, edi);
jmp(&leave_exit_frame);
@@ -1901,10 +1698,10 @@ void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) {
if (call_kind == CALL_AS_FUNCTION) {
// Set to some non-zero smi by updating the least significant
// byte.
- mov_b(dst, 1 << kSmiTagSize);
+ mov_b(Operand(dst), 1 << kSmiTagSize);
} else {
// Set to smi zero by clearing the register.
- xor_(dst, dst);
+ xor_(dst, Operand(dst));
}
}
@@ -1949,7 +1746,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
} else if (!expected.reg().is(actual.reg())) {
// Both expected and actual are in (different) registers. This
// is the case when we invoke functions using call and apply.
- cmp(expected.reg(), actual.reg());
+ cmp(expected.reg(), Operand(actual.reg()));
j(equal, &invoke);
ASSERT(actual.reg().is(eax));
ASSERT(expected.reg().is(ebx));
@@ -1961,7 +1758,7 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
isolate()->builtins()->ArgumentsAdaptorTrampoline();
if (!code_constant.is_null()) {
mov(edx, Immediate(code_constant));
- add(edx, Immediate(Code::kHeaderSize - kHeapObjectTag));
+ add(Operand(edx), Immediate(Code::kHeaderSize - kHeapObjectTag));
} else if (!code_operand.is_reg(edx)) {
mov(edx, code_operand);
}
@@ -1987,9 +1784,6 @@ void MacroAssembler::InvokeCode(const Operand& code,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) {
- // You can't call a function without a valid frame.
- ASSERT(flag == JUMP_FUNCTION || has_frame());
-
Label done;
InvokePrologue(expected, actual, Handle<Code>::null(), code,
&done, flag, Label::kNear, call_wrapper,
@@ -2015,11 +1809,8 @@ void MacroAssembler::InvokeCode(Handle<Code> code,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) {
- // You can't call a function without a valid frame.
- ASSERT(flag == JUMP_FUNCTION || has_frame());
-
Label done;
- Operand dummy(eax, 0);
+ Operand dummy(eax);
InvokePrologue(expected, actual, code, dummy, &done, flag, Label::kNear,
call_wrapper, call_kind);
if (flag == CALL_FUNCTION) {
@@ -2041,9 +1832,6 @@ void MacroAssembler::InvokeFunction(Register fun,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) {
- // You can't call a function without a valid frame.
- ASSERT(flag == JUMP_FUNCTION || has_frame());
-
ASSERT(fun.is(edi));
mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
@@ -2061,9 +1849,6 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
InvokeFlag flag,
const CallWrapper& call_wrapper,
CallKind call_kind) {
- // You can't call a function without a valid frame.
- ASSERT(flag == JUMP_FUNCTION || has_frame());
-
ASSERT(function->is_compiled());
// Get the function and setup the context.
mov(edi, Immediate(Handle<JSFunction>(function)));
@@ -2087,8 +1872,8 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
InvokeFlag flag,
const CallWrapper& call_wrapper) {
- // You can't call a builtin without a valid frame.
- ASSERT(flag == JUMP_FUNCTION || has_frame());
+ // Calls are not allowed in some stubs.
+ ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
// Rely on the assertion to check that the number of provided
// arguments match the expected number of arguments. Fake a
@@ -2099,7 +1884,6 @@ void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
expected, expected, flag, call_wrapper, CALL_AS_METHOD);
}
-
void MacroAssembler::GetBuiltinFunction(Register target,
Builtins::JavaScript id) {
// Load the JavaScript builtin function from the builtins object.
@@ -2109,7 +1893,6 @@ void MacroAssembler::GetBuiltinFunction(Register target,
JSBuiltinsObject::OffsetOfFunctionWithId(id)));
}
-
void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
ASSERT(!target.is(edi));
// Load the JavaScript builtin function from the builtins object.
@@ -2211,7 +1994,7 @@ void MacroAssembler::Ret(int bytes_dropped, Register scratch) {
ret(bytes_dropped);
} else {
pop(scratch);
- add(esp, Immediate(bytes_dropped));
+ add(Operand(esp), Immediate(bytes_dropped));
push(scratch);
ret(0);
}
@@ -2222,7 +2005,7 @@ void MacroAssembler::Ret(int bytes_dropped, Register scratch) {
void MacroAssembler::Drop(int stack_elements) {
if (stack_elements > 0) {
- add(esp, Immediate(stack_elements * kPointerSize));
+ add(Operand(esp), Immediate(stack_elements * kPointerSize));
}
}
@@ -2365,19 +2148,13 @@ void MacroAssembler::Abort(const char* msg) {
RecordComment(msg);
}
#endif
+ // Disable stub call restrictions to always allow calls to abort.
+ AllowStubCallsScope allow_scope(this, true);
push(eax);
push(Immediate(p0));
push(Immediate(reinterpret_cast<intptr_t>(Smi::FromInt(p1 - p0))));
- // Disable stub call restrictions to always allow calls to abort.
- if (!has_frame_) {
- // We don't actually want to generate a pile of code for this, so just
- // claim there is a stack frame, without generating one.
- FrameScope scope(this, StackFrame::NONE);
- CallRuntime(Runtime::kAbort, 2);
- } else {
- CallRuntime(Runtime::kAbort, 2);
- }
+ CallRuntime(Runtime::kAbort, 2);
// will not return here
int3();
}
@@ -2400,7 +2177,7 @@ void MacroAssembler::LoadPowerOf2(XMMRegister dst,
ASSERT(is_uintn(power + HeapNumber::kExponentBias,
HeapNumber::kExponentBits));
mov(scratch, Immediate(power + HeapNumber::kExponentBias));
- movd(dst, scratch);
+ movd(dst, Operand(scratch));
psllq(dst, HeapNumber::kMantissaBits);
}
@@ -2426,8 +2203,8 @@ void MacroAssembler::JumpIfNotBothSequentialAsciiStrings(Register object1,
Label* failure) {
// Check that both objects are not smis.
STATIC_ASSERT(kSmiTag == 0);
- mov(scratch1, object1);
- and_(scratch1, object2);
+ mov(scratch1, Operand(object1));
+ and_(scratch1, Operand(object2));
JumpIfSmi(scratch1, failure);
// Load instance type for both strings.
@@ -2456,12 +2233,12 @@ void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
// Make stack end at alignment and make room for num_arguments words
// and the original value of esp.
mov(scratch, esp);
- sub(esp, Immediate((num_arguments + 1) * kPointerSize));
+ sub(Operand(esp), Immediate((num_arguments + 1) * kPointerSize));
ASSERT(IsPowerOf2(frame_alignment));
and_(esp, -frame_alignment);
mov(Operand(esp, num_arguments * kPointerSize), scratch);
} else {
- sub(esp, Immediate(num_arguments * kPointerSize));
+ sub(Operand(esp), Immediate(num_arguments * kPointerSize));
}
}
@@ -2469,39 +2246,27 @@ void MacroAssembler::PrepareCallCFunction(int num_arguments, Register scratch) {
void MacroAssembler::CallCFunction(ExternalReference function,
int num_arguments) {
// Trashing eax is ok as it will be the return value.
- mov(eax, Immediate(function));
+ mov(Operand(eax), Immediate(function));
CallCFunction(eax, num_arguments);
}
void MacroAssembler::CallCFunction(Register function,
int num_arguments) {
- ASSERT(has_frame());
// Check stack alignment.
if (emit_debug_code()) {
CheckStackAlignment();
}
- call(function);
+ call(Operand(function));
if (OS::ActivationFrameAlignment() != 0) {
mov(esp, Operand(esp, num_arguments * kPointerSize));
} else {
- add(esp, Immediate(num_arguments * kPointerSize));
+ add(Operand(esp), Immediate(num_arguments * kPointerSize));
}
}
-bool AreAliased(Register r1, Register r2, Register r3, Register r4) {
- if (r1.is(r2)) return true;
- if (r1.is(r3)) return true;
- if (r1.is(r4)) return true;
- if (r2.is(r3)) return true;
- if (r2.is(r4)) return true;
- if (r3.is(r4)) return true;
- return false;
-}
-
-
CodePatcher::CodePatcher(byte* address, int size)
: address_(address),
size_(size),
@@ -2523,198 +2288,6 @@ CodePatcher::~CodePatcher() {
}
-void MacroAssembler::CheckPageFlag(
- Register object,
- Register scratch,
- int mask,
- Condition cc,
- Label* condition_met,
- Label::Distance condition_met_distance) {
- ASSERT(cc == zero || cc == not_zero);
- if (scratch.is(object)) {
- and_(scratch, Immediate(~Page::kPageAlignmentMask));
- } else {
- mov(scratch, Immediate(~Page::kPageAlignmentMask));
- and_(scratch, object);
- }
- if (mask < (1 << kBitsPerByte)) {
- test_b(Operand(scratch, MemoryChunk::kFlagsOffset),
- static_cast<uint8_t>(mask));
- } else {
- test(Operand(scratch, MemoryChunk::kFlagsOffset), Immediate(mask));
- }
- j(cc, condition_met, condition_met_distance);
-}
-
-
-void MacroAssembler::JumpIfBlack(Register object,
- Register scratch0,
- Register scratch1,
- Label* on_black,
- Label::Distance on_black_near) {
- HasColor(object, scratch0, scratch1,
- on_black, on_black_near,
- 1, 0); // kBlackBitPattern.
- ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
-}
-
-
-void MacroAssembler::HasColor(Register object,
- Register bitmap_scratch,
- Register mask_scratch,
- Label* has_color,
- Label::Distance has_color_distance,
- int first_bit,
- int second_bit) {
- ASSERT(!AreAliased(object, bitmap_scratch, mask_scratch, ecx));
-
- GetMarkBits(object, bitmap_scratch, mask_scratch);
-
- Label other_color, word_boundary;
- test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
- j(first_bit == 1 ? zero : not_zero, &other_color, Label::kNear);
- add(mask_scratch, mask_scratch); // Shift left 1 by adding.
- j(zero, &word_boundary, Label::kNear);
- test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
- j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
- jmp(&other_color, Label::kNear);
-
- bind(&word_boundary);
- test_b(Operand(bitmap_scratch, MemoryChunk::kHeaderSize + kPointerSize), 1);
-
- j(second_bit == 1 ? not_zero : zero, has_color, has_color_distance);
- bind(&other_color);
-}
-
-
-void MacroAssembler::GetMarkBits(Register addr_reg,
- Register bitmap_reg,
- Register mask_reg) {
- ASSERT(!AreAliased(addr_reg, mask_reg, bitmap_reg, ecx));
- mov(bitmap_reg, Immediate(~Page::kPageAlignmentMask));
- and_(bitmap_reg, addr_reg);
- mov(ecx, addr_reg);
- int shift =
- Bitmap::kBitsPerCellLog2 + kPointerSizeLog2 - Bitmap::kBytesPerCellLog2;
- shr(ecx, shift);
- and_(ecx,
- (Page::kPageAlignmentMask >> shift) & ~(Bitmap::kBytesPerCell - 1));
-
- add(bitmap_reg, ecx);
- mov(ecx, addr_reg);
- shr(ecx, kPointerSizeLog2);
- and_(ecx, (1 << Bitmap::kBitsPerCellLog2) - 1);
- mov(mask_reg, Immediate(1));
- shl_cl(mask_reg);
-}
-
-
-void MacroAssembler::EnsureNotWhite(
- Register value,
- Register bitmap_scratch,
- Register mask_scratch,
- Label* value_is_white_and_not_data,
- Label::Distance distance) {
- ASSERT(!AreAliased(value, bitmap_scratch, mask_scratch, ecx));
- GetMarkBits(value, bitmap_scratch, mask_scratch);
-
- // If the value is black or grey we don't need to do anything.
- ASSERT(strcmp(Marking::kWhiteBitPattern, "00") == 0);
- ASSERT(strcmp(Marking::kBlackBitPattern, "10") == 0);
- ASSERT(strcmp(Marking::kGreyBitPattern, "11") == 0);
- ASSERT(strcmp(Marking::kImpossibleBitPattern, "01") == 0);
-
- Label done;
-
- // Since both black and grey have a 1 in the first position and white does
- // not have a 1 there we only need to check one bit.
- test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
- j(not_zero, &done, Label::kNear);
-
- if (FLAG_debug_code) {
- // Check for impossible bit pattern.
- Label ok;
- push(mask_scratch);
- // shl. May overflow making the check conservative.
- add(mask_scratch, mask_scratch);
- test(mask_scratch, Operand(bitmap_scratch, MemoryChunk::kHeaderSize));
- j(zero, &ok, Label::kNear);
- int3();
- bind(&ok);
- pop(mask_scratch);
- }
-
- // Value is white. We check whether it is data that doesn't need scanning.
- // Currently only checks for HeapNumber and non-cons strings.
- Register map = ecx; // Holds map while checking type.
- Register length = ecx; // Holds length of object after checking type.
- Label not_heap_number;
- Label is_data_object;
-
- // Check for heap-number
- mov(map, FieldOperand(value, HeapObject::kMapOffset));
- cmp(map, FACTORY->heap_number_map());
- j(not_equal, &not_heap_number, Label::kNear);
- mov(length, Immediate(HeapNumber::kSize));
- jmp(&is_data_object, Label::kNear);
-
- bind(&not_heap_number);
- // Check for strings.
- ASSERT(kIsIndirectStringTag == 1 && kIsIndirectStringMask == 1);
- ASSERT(kNotStringTag == 0x80 && kIsNotStringMask == 0x80);
- // If it's a string and it's not a cons string then it's an object containing
- // no GC pointers.
- Register instance_type = ecx;
- movzx_b(instance_type, FieldOperand(map, Map::kInstanceTypeOffset));
- test_b(instance_type, kIsIndirectStringMask | kIsNotStringMask);
- j(not_zero, value_is_white_and_not_data);
- // It's a non-indirect (non-cons and non-slice) string.
- // If it's external, the length is just ExternalString::kSize.
- // Otherwise it's String::kHeaderSize + string->length() * (1 or 2).
- Label not_external;
- // External strings are the only ones with the kExternalStringTag bit
- // set.
- ASSERT_EQ(0, kSeqStringTag & kExternalStringTag);
- ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
- test_b(instance_type, kExternalStringTag);
- j(zero, &not_external, Label::kNear);
- mov(length, Immediate(ExternalString::kSize));
- jmp(&is_data_object, Label::kNear);
-
- bind(&not_external);
- // Sequential string, either ASCII or UC16.
- ASSERT(kAsciiStringTag == 0x04);
- and_(length, Immediate(kStringEncodingMask));
- xor_(length, Immediate(kStringEncodingMask));
- add(length, Immediate(0x04));
- // Value now either 4 (if ASCII) or 8 (if UC16), i.e., char-size shifted
- // by 2. If we multiply the string length as smi by this, it still
- // won't overflow a 32-bit value.
- ASSERT_EQ(SeqAsciiString::kMaxSize, SeqTwoByteString::kMaxSize);
- ASSERT(SeqAsciiString::kMaxSize <=
- static_cast<int>(0xffffffffu >> (2 + kSmiTagSize)));
- imul(length, FieldOperand(value, String::kLengthOffset));
- shr(length, 2 + kSmiTagSize + kSmiShiftSize);
- add(length, Immediate(SeqString::kHeaderSize + kObjectAlignmentMask));
- and_(length, Immediate(~kObjectAlignmentMask));
-
- bind(&is_data_object);
- // Value is a data object, and it is white. Mark it black. Since we know
- // that the object is white we can make it black by flipping one bit.
- or_(Operand(bitmap_scratch, MemoryChunk::kHeaderSize), mask_scratch);
-
- and_(bitmap_scratch, Immediate(~Page::kPageAlignmentMask));
- add(Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset),
- length);
- if (FLAG_debug_code) {
- mov(length, Operand(bitmap_scratch, MemoryChunk::kLiveBytesOffset));
- cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset));
- Check(less_equal, "Live Bytes Count overflow chunk size");
- }
-
- bind(&done);
-}
-
} } // namespace v8::internal
#endif // V8_TARGET_ARCH_IA32