aboutsummaryrefslogtreecommitdiff
path: root/src/ia32/codegen-ia32.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ia32/codegen-ia32.cc')
-rw-r--r--src/ia32/codegen-ia32.cc356
1 files changed, 26 insertions, 330 deletions
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 18e53641..fd7b9cac 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -485,315 +485,15 @@ MemMoveFunction CreateMemMoveFunction(Isolate* isolate) {
#define __ ACCESS_MASM(masm)
-
-void ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
- MacroAssembler* masm,
- Register receiver,
- Register key,
- Register value,
- Register target_map,
- AllocationSiteMode mode,
- Label* allocation_memento_found) {
- Register scratch = edi;
- DCHECK(!AreAliased(receiver, key, value, target_map, scratch));
-
- if (mode == TRACK_ALLOCATION_SITE) {
- DCHECK(allocation_memento_found != NULL);
- __ JumpIfJSArrayHasAllocationMemento(
- receiver, scratch, allocation_memento_found);
- }
-
- // Set transitioned map.
- __ mov(FieldOperand(receiver, HeapObject::kMapOffset), target_map);
- __ RecordWriteField(receiver,
- HeapObject::kMapOffset,
- target_map,
- scratch,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
-}
-
-
-void ElementsTransitionGenerator::GenerateSmiToDouble(
- MacroAssembler* masm,
- Register receiver,
- Register key,
- Register value,
- Register target_map,
- AllocationSiteMode mode,
- Label* fail) {
- // Return address is on the stack.
- DCHECK(receiver.is(edx));
- DCHECK(key.is(ecx));
- DCHECK(value.is(eax));
- DCHECK(target_map.is(ebx));
-
- Label loop, entry, convert_hole, gc_required, only_change_map;
-
- if (mode == TRACK_ALLOCATION_SITE) {
- __ JumpIfJSArrayHasAllocationMemento(edx, edi, fail);
- }
-
- // Check for empty arrays, which only require a map transition and no changes
- // to the backing store.
- __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
- __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
- __ j(equal, &only_change_map);
-
- __ push(eax);
- __ push(ebx);
- __ push(esi);
-
- __ mov(edi, FieldOperand(edi, FixedArray::kLengthOffset));
-
- // Allocate new FixedDoubleArray.
- // edx: receiver
- // edi: length of source FixedArray (smi-tagged)
- AllocationFlags flags = static_cast<AllocationFlags>(DOUBLE_ALIGNMENT);
- __ Allocate(FixedDoubleArray::kHeaderSize, times_8, edi,
- REGISTER_VALUE_IS_SMI, eax, ebx, no_reg, &gc_required, flags);
-
- // eax: destination FixedDoubleArray
- // edi: number of elements
- // edx: receiver
- __ mov(FieldOperand(eax, HeapObject::kMapOffset),
- Immediate(masm->isolate()->factory()->fixed_double_array_map()));
- __ mov(FieldOperand(eax, FixedDoubleArray::kLengthOffset), edi);
- __ mov(esi, FieldOperand(edx, JSObject::kElementsOffset));
- // Replace receiver's backing store with newly created FixedDoubleArray.
- __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax);
- __ mov(ebx, eax);
- __ RecordWriteField(edx,
- JSObject::kElementsOffset,
- ebx,
- edi,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
-
- __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset));
-
- // Prepare for conversion loop.
- ExternalReference canonical_the_hole_nan_reference =
- ExternalReference::address_of_the_hole_nan();
- XMMRegister the_hole_nan = xmm1;
- __ movsd(the_hole_nan,
- Operand::StaticVariable(canonical_the_hole_nan_reference));
- __ jmp(&entry);
-
- // Call into runtime if GC is required.
- __ bind(&gc_required);
-
- // Restore registers before jumping into runtime.
- __ pop(esi);
- __ pop(ebx);
- __ pop(eax);
- __ jmp(fail);
-
- // Convert and copy elements
- // esi: source FixedArray
- __ bind(&loop);
- __ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize));
- // ebx: current element from source
- // edi: index of current element
- __ JumpIfNotSmi(ebx, &convert_hole);
-
- // Normal smi, convert it to double and store.
- __ SmiUntag(ebx);
- __ Cvtsi2sd(xmm0, ebx);
- __ movsd(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize),
- xmm0);
- __ jmp(&entry);
-
- // Found hole, store hole_nan_as_double instead.
- __ bind(&convert_hole);
-
- if (FLAG_debug_code) {
- __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
- __ Assert(equal, kObjectFoundInSmiOnlyArray);
- }
-
- __ movsd(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize),
- the_hole_nan);
-
- __ bind(&entry);
- __ sub(edi, Immediate(Smi::FromInt(1)));
- __ j(not_sign, &loop);
-
- // Restore registers.
- __ pop(esi);
- __ pop(ebx);
- __ pop(eax);
-
- __ bind(&only_change_map);
- // eax: value
- // ebx: target map
- // Set transitioned map.
- __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
- __ RecordWriteField(edx,
- HeapObject::kMapOffset,
- ebx,
- edi,
- kDontSaveFPRegs,
- OMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
-}
-
-
-void ElementsTransitionGenerator::GenerateDoubleToObject(
- MacroAssembler* masm,
- Register receiver,
- Register key,
- Register value,
- Register target_map,
- AllocationSiteMode mode,
- Label* fail) {
- // Return address is on the stack.
- DCHECK(receiver.is(edx));
- DCHECK(key.is(ecx));
- DCHECK(value.is(eax));
- DCHECK(target_map.is(ebx));
-
- Label loop, entry, convert_hole, gc_required, only_change_map, success;
-
- if (mode == TRACK_ALLOCATION_SITE) {
- __ JumpIfJSArrayHasAllocationMemento(edx, edi, fail);
- }
-
- // Check for empty arrays, which only require a map transition and no changes
- // to the backing store.
- __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
- __ cmp(edi, Immediate(masm->isolate()->factory()->empty_fixed_array()));
- __ j(equal, &only_change_map);
-
- __ push(esi);
- __ push(eax);
- __ push(edx);
- __ push(ebx);
-
- __ mov(ebx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
-
- // Allocate new FixedArray.
- // ebx: length of source FixedDoubleArray (smi-tagged)
- __ lea(edi, Operand(ebx, times_2, FixedArray::kHeaderSize));
- __ Allocate(edi, eax, esi, no_reg, &gc_required, NO_ALLOCATION_FLAGS);
-
- // eax: destination FixedArray
- // ebx: number of elements
- __ mov(FieldOperand(eax, HeapObject::kMapOffset),
- Immediate(masm->isolate()->factory()->fixed_array_map()));
- __ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx);
- __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
-
- // Allocating heap numbers in the loop below can fail and cause a jump to
- // gc_required. We can't leave a partly initialized FixedArray behind,
- // so pessimistically fill it with holes now.
- Label initialization_loop, initialization_loop_entry;
- __ jmp(&initialization_loop_entry, Label::kNear);
- __ bind(&initialization_loop);
- __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize),
- masm->isolate()->factory()->the_hole_value());
- __ bind(&initialization_loop_entry);
- __ sub(ebx, Immediate(Smi::FromInt(1)));
- __ j(not_sign, &initialization_loop);
-
- __ mov(ebx, FieldOperand(edi, FixedDoubleArray::kLengthOffset));
- __ jmp(&entry);
-
- // ebx: target map
- // edx: receiver
- // Set transitioned map.
- __ bind(&only_change_map);
- __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
- __ RecordWriteField(edx,
- HeapObject::kMapOffset,
- ebx,
- edi,
- kDontSaveFPRegs,
- OMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- __ jmp(&success);
-
- // Call into runtime if GC is required.
- __ bind(&gc_required);
- __ pop(ebx);
- __ pop(edx);
- __ pop(eax);
- __ pop(esi);
- __ jmp(fail);
-
- // Box doubles into heap numbers.
- // edi: source FixedDoubleArray
- // eax: destination FixedArray
- __ bind(&loop);
- // ebx: index of current element (smi-tagged)
- uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
- __ cmp(FieldOperand(edi, ebx, times_4, offset), Immediate(kHoleNanUpper32));
- __ j(equal, &convert_hole);
-
- // Non-hole double, copy value into a heap number.
- __ AllocateHeapNumber(edx, esi, no_reg, &gc_required);
- // edx: new heap number
- __ movsd(xmm0,
- FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize));
- __ movsd(FieldOperand(edx, HeapNumber::kValueOffset), xmm0);
- __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), edx);
- __ mov(esi, ebx);
- __ RecordWriteArray(eax,
- edx,
- esi,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- __ jmp(&entry, Label::kNear);
-
- // Replace the-hole NaN with the-hole pointer.
- __ bind(&convert_hole);
- __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize),
- masm->isolate()->factory()->the_hole_value());
-
- __ bind(&entry);
- __ sub(ebx, Immediate(Smi::FromInt(1)));
- __ j(not_sign, &loop);
-
- __ pop(ebx);
- __ pop(edx);
- // ebx: target map
- // edx: receiver
- // Set transitioned map.
- __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx);
- __ RecordWriteField(edx,
- HeapObject::kMapOffset,
- ebx,
- edi,
- kDontSaveFPRegs,
- OMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
- // Replace receiver's backing store with newly created and filled FixedArray.
- __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax);
- __ RecordWriteField(edx,
- JSObject::kElementsOffset,
- eax,
- edi,
- kDontSaveFPRegs,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
-
- // Restore registers.
- __ pop(eax);
- __ pop(esi);
-
- __ bind(&success);
-}
-
-
void StringCharLoadGenerator::Generate(MacroAssembler* masm,
Factory* factory,
Register string,
Register index,
Register result,
Label* call_runtime) {
+ Label indirect_string_loaded;
+ __ bind(&indirect_string_loaded);
+
// Fetch the instance type of the receiver into result register.
__ mov(result, FieldOperand(string, HeapObject::kMapOffset));
__ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
@@ -804,17 +504,24 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
__ j(zero, &check_sequential, Label::kNear);
// Dispatch on the indirect string shape: slice or cons.
- Label cons_string;
- __ test(result, Immediate(kSlicedNotConsMask));
- __ j(zero, &cons_string, Label::kNear);
+ Label cons_string, thin_string;
+ __ and_(result, Immediate(kStringRepresentationMask));
+ __ cmp(result, Immediate(kConsStringTag));
+ __ j(equal, &cons_string, Label::kNear);
+ __ cmp(result, Immediate(kThinStringTag));
+ __ j(equal, &thin_string, Label::kNear);
// Handle slices.
- Label indirect_string_loaded;
__ mov(result, FieldOperand(string, SlicedString::kOffsetOffset));
__ SmiUntag(result);
__ add(index, result);
__ mov(string, FieldOperand(string, SlicedString::kParentOffset));
- __ jmp(&indirect_string_loaded, Label::kNear);
+ __ jmp(&indirect_string_loaded);
+
+ // Handle thin strings.
+ __ bind(&thin_string);
+ __ mov(string, FieldOperand(string, ThinString::kActualOffset));
+ __ jmp(&indirect_string_loaded);
// Handle cons strings.
// Check whether the right hand side is the empty string (i.e. if
@@ -826,10 +533,7 @@ void StringCharLoadGenerator::Generate(MacroAssembler* masm,
Immediate(factory->empty_string()));
__ j(not_equal, call_runtime);
__ mov(string, FieldOperand(string, ConsString::kFirstOffset));
-
- __ bind(&indirect_string_loaded);
- __ mov(result, FieldOperand(string, HeapObject::kMapOffset));
- __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset));
+ __ jmp(&indirect_string_loaded);
// Distinguish sequential and external strings. Only these two string
// representations can reach here (slices and flat cons strings have been
@@ -919,32 +623,24 @@ bool Code::IsYoungSequence(Isolate* isolate, byte* sequence) {
return result;
}
+Code::Age Code::GetCodeAge(Isolate* isolate, byte* sequence) {
+ if (IsYoungSequence(isolate, sequence)) return kNoAgeCodeAge;
-void Code::GetCodeAgeAndParity(Isolate* isolate, byte* sequence, Age* age,
- MarkingParity* parity) {
- if (IsYoungSequence(isolate, sequence)) {
- *age = kNoAgeCodeAge;
- *parity = NO_MARKING_PARITY;
- } else {
- sequence++; // Skip the kCallOpcode byte
- Address target_address = sequence + *reinterpret_cast<int*>(sequence) +
- Assembler::kCallTargetAddressOffset;
- Code* stub = GetCodeFromTargetAddress(target_address);
- GetCodeAgeAndParity(stub, age, parity);
- }
+ sequence++; // Skip the kCallOpcode byte
+ Address target_address = sequence + *reinterpret_cast<int*>(sequence) +
+ Assembler::kCallTargetAddressOffset;
+ Code* stub = GetCodeFromTargetAddress(target_address);
+ return GetAgeOfCodeAgeStub(stub);
}
-
-void Code::PatchPlatformCodeAge(Isolate* isolate,
- byte* sequence,
- Code::Age age,
- MarkingParity parity) {
+void Code::PatchPlatformCodeAge(Isolate* isolate, byte* sequence,
+ Code::Age age) {
uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
if (age == kNoAgeCodeAge) {
isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
Assembler::FlushICache(isolate, sequence, young_length);
} else {
- Code* stub = GetCodeAgeStub(isolate, age, parity);
+ Code* stub = GetCodeAgeStub(isolate, age);
CodePatcher patcher(isolate, sequence, young_length);
patcher.masm()->call(stub->instruction_start(), RelocInfo::NONE32);
}