OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #if defined(V8_TARGET_ARCH_IA32) | 30 #if defined(V8_TARGET_ARCH_IA32) |
31 | 31 |
32 #include "bootstrapper.h" | 32 #include "bootstrapper.h" |
33 #include "code-stubs.h" | 33 #include "code-stubs.h" |
34 #include "isolate.h" | 34 #include "isolate.h" |
35 #include "jsregexp.h" | 35 #include "jsregexp.h" |
36 #include "regexp-macro-assembler.h" | 36 #include "regexp-macro-assembler.h" |
| 37 #include "stub-cache.h" |
37 | 38 |
38 namespace v8 { | 39 namespace v8 { |
39 namespace internal { | 40 namespace internal { |
40 | 41 |
41 #define __ ACCESS_MASM(masm) | 42 #define __ ACCESS_MASM(masm) |
42 | 43 |
43 void ToNumberStub::Generate(MacroAssembler* masm) { | 44 void ToNumberStub::Generate(MacroAssembler* masm) { |
44 // The ToNumber stub takes one argument in eax. | 45 // The ToNumber stub takes one argument in eax. |
45 Label check_heap_number, call_builtin; | 46 Label check_heap_number, call_builtin; |
46 __ JumpIfNotSmi(eax, &check_heap_number, Label::kNear); | 47 __ JumpIfNotSmi(eax, &check_heap_number, Label::kNear); |
(...skipping 6695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6742 { edx, ecx, ebx, EMIT_REMEMBERED_SET }, | 6743 { edx, ecx, ebx, EMIT_REMEMBERED_SET }, |
6743 // GenerateStoreField calls the stub with two different permutations of | 6744 // GenerateStoreField calls the stub with two different permutations of |
6744 // registers. This is the second. | 6745 // registers. This is the second. |
6745 { ebx, ecx, edx, EMIT_REMEMBERED_SET }, | 6746 { ebx, ecx, edx, EMIT_REMEMBERED_SET }, |
6746 // StoreIC::GenerateNormal via GenerateDictionaryStore | 6747 // StoreIC::GenerateNormal via GenerateDictionaryStore |
6747 { ebx, edi, edx, EMIT_REMEMBERED_SET }, | 6748 { ebx, edi, edx, EMIT_REMEMBERED_SET }, |
6748 // KeyedStoreIC::GenerateGeneric. | 6749 // KeyedStoreIC::GenerateGeneric. |
6749 { ebx, edx, ecx, EMIT_REMEMBERED_SET}, | 6750 { ebx, edx, ecx, EMIT_REMEMBERED_SET}, |
6750 // KeyedStoreStubCompiler::GenerateStoreFastElement. | 6751 // KeyedStoreStubCompiler::GenerateStoreFastElement. |
6751 { edi, edx, ecx, EMIT_REMEMBERED_SET}, | 6752 { edi, edx, ecx, EMIT_REMEMBERED_SET}, |
| 6753 // FastElementConversionStub::GenerateSmiOnlyToObject |
| 6754 // and FastElementsConversionStub::GenerateSmiOnlyToDouble |
| 6755 // and FastElementsConversionStub::GenerateDoubleToObject |
| 6756 { edx, ebx, edi, EMIT_REMEMBERED_SET}, |
| 6757 // FastElementConversionStub::GenerateDoubleToObject |
| 6758 { eax, edx, esi, EMIT_REMEMBERED_SET}, |
| 6759 { edx, eax, edi, EMIT_REMEMBERED_SET}, |
6752 // Null termination. | 6760 // Null termination. |
6753 { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET} | 6761 { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET} |
6754 }; | 6762 }; |
6755 | 6763 |
6756 | 6764 |
6757 bool RecordWriteStub::IsPregenerated() { | 6765 bool RecordWriteStub::IsPregenerated() { |
6758 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; | 6766 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; |
6759 !entry->object.is(no_reg); | 6767 !entry->object.is(no_reg); |
6760 entry++) { | 6768 entry++) { |
6761 if (object_.is(entry->object) && | 6769 if (object_.is(entry->object) && |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6985 | 6993 |
6986 __ bind(&need_incremental_pop_object); | 6994 __ bind(&need_incremental_pop_object); |
6987 __ pop(regs_.object()); | 6995 __ pop(regs_.object()); |
6988 | 6996 |
6989 __ bind(&need_incremental); | 6997 __ bind(&need_incremental); |
6990 | 6998 |
6991 // Fall through when we need to inform the incremental marker. | 6999 // Fall through when we need to inform the incremental marker. |
6992 } | 7000 } |
6993 | 7001 |
6994 | 7002 |
| 7003 void FastElementsConversionStub::GenerateSmiOnlyToObject(MacroAssembler* masm) { |
| 7004 // ----------- S t a t e ------------- |
| 7005 // -- eax : value |
| 7006 // -- ebx : target map |
| 7007 // -- ecx : key |
| 7008 // -- edx : receiver |
| 7009 // -- esp[0] : return address |
| 7010 // ----------------------------------- |
| 7011 // Set transitioned map. |
| 7012 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); |
| 7013 __ RecordWriteField(edx, |
| 7014 HeapObject::kMapOffset, |
| 7015 ebx, |
| 7016 edi, |
| 7017 kDontSaveFPRegs, |
| 7018 EMIT_REMEMBERED_SET, |
| 7019 OMIT_SMI_CHECK); |
| 7020 } |
| 7021 |
| 7022 |
| 7023 void FastElementsConversionStub::GenerateSmiOnlyToDouble( |
| 7024 MacroAssembler* masm, StrictModeFlag strict_mode) { |
| 7025 // ----------- S t a t e ------------- |
| 7026 // -- eax : value |
| 7027 // -- ebx : target map |
| 7028 // -- ecx : key |
| 7029 // -- edx : receiver |
| 7030 // -- esp[0] : return address |
| 7031 // ----------------------------------- |
| 7032 Label loop, entry, convert_hole, gc_required; |
| 7033 __ push(eax); |
| 7034 __ push(ebx); |
| 7035 |
| 7036 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 7037 __ mov(edi, FieldOperand(edi, FixedArray::kLengthOffset)); |
| 7038 |
| 7039 // Allocate new FixedDoubleArray. |
| 7040 // edx: receiver |
| 7041 // edi: length of source FixedArray (smi-tagged) |
| 7042 __ lea(esi, Operand(edi, times_4, FixedDoubleArray::kHeaderSize)); |
| 7043 __ AllocateInNewSpace(esi, eax, ebx, no_reg, &gc_required, TAG_OBJECT); |
| 7044 |
| 7045 // eax: destination FixedDoubleArray |
| 7046 // edi: number of elements |
| 7047 // edx: receiver |
| 7048 __ mov(FieldOperand(eax, HeapObject::kMapOffset), |
| 7049 Immediate(masm->isolate()->factory()->fixed_double_array_map())); |
| 7050 __ mov(FieldOperand(eax, FixedDoubleArray::kLengthOffset), edi); |
| 7051 __ mov(esi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 7052 // Replace receiver's backing store with newly created FixedDoubleArray. |
| 7053 __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax); |
| 7054 __ mov(ebx, eax); |
| 7055 __ RecordWriteField(edx, |
| 7056 JSObject::kElementsOffset, |
| 7057 ebx, |
| 7058 edi, |
| 7059 kDontSaveFPRegs, |
| 7060 EMIT_REMEMBERED_SET, |
| 7061 OMIT_SMI_CHECK); |
| 7062 |
| 7063 __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset)); |
| 7064 // Convert and copy elements |
| 7065 // esi: source FixedArray |
| 7066 // edi: number of elements to convert/copy |
| 7067 ExternalReference canonical_the_hole_nan_reference = |
| 7068 ExternalReference::address_of_the_hole_nan(); |
| 7069 XMMRegister the_hole_nan = xmm1; |
| 7070 if (CpuFeatures::IsSupported(SSE2)) { |
| 7071 CpuFeatures::Scope use_sse2(SSE2); |
| 7072 __ movdbl(the_hole_nan, |
| 7073 Operand::StaticVariable(canonical_the_hole_nan_reference)); |
| 7074 } |
| 7075 __ jmp(&entry); |
| 7076 __ bind(&loop); |
| 7077 __ sub(edi, Immediate(Smi::FromInt(1))); |
| 7078 __ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize)); |
| 7079 // ebx: current element from source |
| 7080 // edi: index of current element |
| 7081 __ JumpIfNotSmi(ebx, &convert_hole); |
| 7082 |
| 7083 // Normal smi, convert it to double and store. |
| 7084 __ SmiUntag(ebx); |
| 7085 if (CpuFeatures::IsSupported(SSE2)) { |
| 7086 CpuFeatures::Scope fscope(SSE2); |
| 7087 __ cvtsi2sd(xmm0, ebx); |
| 7088 __ movdbl(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize), |
| 7089 xmm0); |
| 7090 } else { |
| 7091 __ push(ebx); |
| 7092 __ fild_s(Operand(esp, 0)); |
| 7093 __ pop(ebx); |
| 7094 __ fstp_d(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize)); |
| 7095 } |
| 7096 __ jmp(&entry); |
| 7097 |
| 7098 // Found hole, store hole_nan_as_double instead. |
| 7099 __ bind(&convert_hole); |
| 7100 if (CpuFeatures::IsSupported(SSE2)) { |
| 7101 CpuFeatures::Scope use_sse2(SSE2); |
| 7102 __ movdbl(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize), |
| 7103 the_hole_nan); |
| 7104 } else { |
| 7105 __ fld_d(Operand::StaticVariable(canonical_the_hole_nan_reference)); |
| 7106 __ fstp_d(FieldOperand(eax, edi, times_4, FixedDoubleArray::kHeaderSize)); |
| 7107 } |
| 7108 |
| 7109 __ bind(&entry); |
| 7110 __ test(edi, edi); |
| 7111 __ j(not_zero, &loop); |
| 7112 |
| 7113 Label done; |
| 7114 __ pop(ebx); |
| 7115 __ pop(eax); |
| 7116 // eax: value |
| 7117 // ebx: target map |
| 7118 // Set transitioned map. |
| 7119 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); |
| 7120 __ RecordWriteField(edx, |
| 7121 HeapObject::kMapOffset, |
| 7122 ebx, |
| 7123 edi, |
| 7124 kDontSaveFPRegs, |
| 7125 EMIT_REMEMBERED_SET, |
| 7126 OMIT_SMI_CHECK); |
| 7127 // Restore esi. |
| 7128 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 7129 __ jmp(&done, Label::kNear); |
| 7130 |
| 7131 __ bind(&gc_required); |
| 7132 // Restore registers before jumping into runtime. |
| 7133 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 7134 __ pop(ebx); |
| 7135 __ pop(eax); |
| 7136 KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode); |
| 7137 __ bind(&done); |
| 7138 } |
| 7139 |
| 7140 |
| 7141 void FastElementsConversionStub::GenerateDoubleToObject( |
| 7142 MacroAssembler* masm, StrictModeFlag strict_mode) { |
| 7143 // ----------- S t a t e ------------- |
| 7144 // -- eax : value |
| 7145 // -- ebx : target map |
| 7146 // -- ecx : key |
| 7147 // -- edx : receiver |
| 7148 // -- esp[0] : return address |
| 7149 // ----------------------------------- |
| 7150 Label loop, entry, convert_hole, gc_required; |
| 7151 __ push(eax); |
| 7152 __ push(edx); |
| 7153 __ push(ebx); |
| 7154 |
| 7155 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 7156 __ mov(ebx, FieldOperand(edi, FixedDoubleArray::kLengthOffset)); |
| 7157 |
| 7158 // Allocate new FixedArray. |
| 7159 // ebx: length of source FixedDoubleArray (smi-tagged) |
| 7160 __ lea(edi, Operand(ebx, times_2, FixedArray::kHeaderSize)); |
| 7161 __ AllocateInNewSpace(edi, eax, esi, no_reg, &gc_required, TAG_OBJECT); |
| 7162 |
| 7163 // eax: destination FixedArray |
| 7164 // ebx: number of elements |
| 7165 __ mov(FieldOperand(eax, HeapObject::kMapOffset), |
| 7166 Immediate(masm->isolate()->factory()->fixed_array_map())); |
| 7167 __ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx); |
| 7168 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 7169 |
| 7170 // Box doubles into heap numbers. |
| 7171 // edi: source FixedDoubleArray |
| 7172 // eax: destination FixedArray |
| 7173 __ jmp(&entry); |
| 7174 __ bind(&loop); |
| 7175 __ sub(ebx, Immediate(Smi::FromInt(1))); |
| 7176 // ebx: index of current element (smi-tagged) |
| 7177 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); |
| 7178 __ cmp(FieldOperand(edi, ebx, times_4, offset), Immediate(kHoleNanUpper32)); |
| 7179 __ j(equal, &convert_hole); |
| 7180 |
| 7181 // Non-hole double, copy value into a heap number. |
| 7182 __ AllocateHeapNumber(edx, esi, no_reg, &gc_required); |
| 7183 // edx: new heap number |
| 7184 if (CpuFeatures::IsSupported(SSE2)) { |
| 7185 CpuFeatures::Scope fscope(SSE2); |
| 7186 __ movdbl(xmm0, |
| 7187 FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize)); |
| 7188 __ movdbl(FieldOperand(edx, HeapNumber::kValueOffset), xmm0); |
| 7189 } else { |
| 7190 __ mov(esi, FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize)); |
| 7191 __ mov(FieldOperand(edx, HeapNumber::kValueOffset), esi); |
| 7192 __ mov(esi, FieldOperand(edi, ebx, times_4, offset)); |
| 7193 __ mov(FieldOperand(edx, HeapNumber::kValueOffset + kPointerSize), esi); |
| 7194 } |
| 7195 __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), edx); |
| 7196 __ mov(esi, ebx); |
| 7197 __ RecordWriteArray(eax, |
| 7198 edx, |
| 7199 esi, |
| 7200 kDontSaveFPRegs, |
| 7201 EMIT_REMEMBERED_SET, |
| 7202 OMIT_SMI_CHECK); |
| 7203 __ jmp(&entry); |
| 7204 |
| 7205 // Replace the-hole nan with the-hole pointer. |
| 7206 __ bind(&convert_hole); |
| 7207 __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), |
| 7208 masm->isolate()->factory()->the_hole_value()); |
| 7209 |
| 7210 __ bind(&entry); |
| 7211 __ test(ebx, ebx); |
| 7212 __ j(not_zero, &loop); |
| 7213 |
| 7214 __ pop(ebx); |
| 7215 __ pop(edx); |
| 7216 // ebx: target map |
| 7217 // edx: receiver |
| 7218 // Set transitioned map. |
| 7219 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); |
| 7220 __ RecordWriteField(edx, |
| 7221 HeapObject::kMapOffset, |
| 7222 ebx, |
| 7223 edi, |
| 7224 kDontSaveFPRegs, |
| 7225 EMIT_REMEMBERED_SET, |
| 7226 OMIT_SMI_CHECK); |
| 7227 // Replace receiver's backing store with newly created and filled FixedArray. |
| 7228 __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax); |
| 7229 __ RecordWriteField(edx, |
| 7230 JSObject::kElementsOffset, |
| 7231 eax, |
| 7232 edi, |
| 7233 kDontSaveFPRegs, |
| 7234 EMIT_REMEMBERED_SET, |
| 7235 OMIT_SMI_CHECK); |
| 7236 |
| 7237 // Restore registers. |
| 7238 Label done; |
| 7239 __ pop(eax); |
| 7240 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 7241 __ jmp(&done, Label::kNear); |
| 7242 |
| 7243 __ bind(&gc_required); |
| 7244 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 7245 __ pop(ebx); |
| 7246 __ pop(edx); |
| 7247 __ pop(eax); |
| 7248 KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode); |
| 7249 __ bind(&done); |
| 7250 } |
| 7251 |
6995 #undef __ | 7252 #undef __ |
6996 | 7253 |
6997 } } // namespace v8::internal | 7254 } } // namespace v8::internal |
6998 | 7255 |
6999 #endif // V8_TARGET_ARCH_IA32 | 7256 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |