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}, | |
6752 // Null termination. | 6759 // Null termination. |
6753 { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET} | 6760 { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET} |
6754 }; | 6761 }; |
6755 | 6762 |
6756 | 6763 |
6757 bool RecordWriteStub::IsPregenerated() { | 6764 bool RecordWriteStub::IsPregenerated() { |
6758 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; | 6765 for (AheadOfTimeWriteBarrierStubList* entry = kAheadOfTime; |
6759 !entry->object.is(no_reg); | 6766 !entry->object.is(no_reg); |
6760 entry++) { | 6767 entry++) { |
6761 if (object_.is(entry->object) && | 6768 if (object_.is(entry->object) && |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6985 | 6992 |
6986 __ bind(&need_incremental_pop_object); | 6993 __ bind(&need_incremental_pop_object); |
6987 __ pop(regs_.object()); | 6994 __ pop(regs_.object()); |
6988 | 6995 |
6989 __ bind(&need_incremental); | 6996 __ bind(&need_incremental); |
6990 | 6997 |
6991 // Fall through when we need to inform the incremental marker. | 6998 // Fall through when we need to inform the incremental marker. |
6992 } | 6999 } |
6993 | 7000 |
6994 | 7001 |
7002 void FastElementsConversionStub::GenerateSmiOnlyToObject(MacroAssembler* masm) { | |
7003 // ----------- S t a t e ------------- | |
7004 // -- eax : value | |
7005 // -- ebx : target map | |
7006 // -- ecx : key | |
7007 // -- edx : receiver | |
7008 // -- esp[0] : return address | |
7009 // ----------------------------------- | |
7010 // Set transitioned map. | |
7011 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); | |
7012 __ RecordWriteField(edx, | |
7013 HeapObject::kMapOffset, | |
7014 ebx, | |
7015 edi, | |
7016 kDontSaveFPRegs, | |
7017 EMIT_REMEMBERED_SET, | |
7018 OMIT_SMI_CHECK); | |
7019 } | |
7020 | |
7021 | |
7022 void FastElementsConversionStub::GenerateSmiOnlyToDouble( | |
7023 MacroAssembler* masm, StrictModeFlag strict_mode) { | |
7024 // ----------- S t a t e ------------- | |
7025 // -- eax : value | |
7026 // -- ebx : target map | |
7027 // -- ecx : key | |
7028 // -- edx : receiver | |
7029 // -- esp[0] : return address | |
7030 // ----------------------------------- | |
7031 Label loop, entry, convert_hole, gc_required; | |
7032 __ push(eax); | |
7033 __ push(ebx); | |
7034 | |
7035 __ mov(esi, FieldOperand(edx, JSObject::kElementsOffset)); | |
7036 __ mov(esi, FieldOperand(esi, FixedArray::kLengthOffset)); | |
7037 | |
7038 // Allocate new FixedDoubleArray. | |
7039 // edx: receiver | |
7040 // esi: length of source FixedArray (smi-tagged) | |
7041 __ lea(edi, Operand(esi, times_4, FixedDoubleArray::kHeaderSize)); | |
7042 __ AllocateInNewSpace(edi, eax, ebx, no_reg, &gc_required, TAG_OBJECT); | |
7043 | |
7044 // eax: destination FixedDoubleArray | |
7045 // esi: number of elements | |
7046 // edx: receiver | |
7047 // edi: source FixedArray | |
Jakob Kummerow
2011/10/13 09:15:59
Please move this comment to some place where the s
| |
7048 __ mov(FieldOperand(eax, HeapObject::kMapOffset), | |
7049 Immediate(masm->isolate()->factory()->fixed_double_array_map())); | |
7050 __ mov(FieldOperand(eax, FixedDoubleArray::kLengthOffset), esi); | |
7051 // Replace receiver's backing store with newly created FixedDoubleArray. | |
7052 __ mov(ebx, eax); | |
7053 __ RecordWriteField(edx, | |
7054 JSObject::kElementsOffset, | |
7055 ebx, | |
7056 edi, | |
7057 kDontSaveFPRegs, | |
7058 EMIT_REMEMBERED_SET, | |
7059 OMIT_SMI_CHECK); | |
7060 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | |
7061 // Write barrier has been notified earlier. | |
7062 __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax); | |
7063 | |
7064 // Convert and copy elements | |
7065 // edi: source FixedArray | |
Jakob Kummerow
2011/10/13 09:15:59
You can omit all comments for registers whose cont
Yang
2011/10/13 09:58:53
Done.
| |
7066 // eax: destination FixedDoubleArray | |
7067 // esi: number of elements to convert/copy | |
7068 // edx: receiver | |
7069 ExternalReference canonical_the_hole_nan_reference = | |
7070 ExternalReference::address_of_the_hole_nan(); | |
7071 XMMRegister the_hole_nan = xmm1; | |
7072 if (CpuFeatures::IsSupported(SSE2)) { | |
7073 CpuFeatures::Scope use_sse2(SSE2); | |
7074 __ movdbl(the_hole_nan, | |
7075 Operand::StaticVariable(canonical_the_hole_nan_reference)); | |
7076 } | |
7077 __ jmp(&entry); | |
7078 __ bind(&loop); | |
7079 __ sub(esi, Immediate(Smi::FromInt(1))); | |
7080 __ mov(ebx, FieldOperand(edi, esi, times_2, FixedArray::kHeaderSize)); | |
7081 // ebx: current element from source | |
7082 // esi: index of current element | |
7083 __ JumpIfNotSmi(ebx, &convert_hole); | |
7084 | |
7085 // Normal smi, convert it to double and store. | |
7086 __ SmiUntag(ebx); | |
7087 if (CpuFeatures::IsSupported(SSE2)) { | |
7088 CpuFeatures::Scope fscope(SSE2); | |
7089 __ cvtsi2sd(xmm0, ebx); | |
7090 __ movdbl(FieldOperand(eax, esi, times_4, FixedDoubleArray::kHeaderSize), | |
7091 xmm0); | |
7092 } else { | |
7093 __ push(ebx); | |
7094 __ fild_s(Operand(esp, 0)); | |
7095 __ pop(ebx); | |
7096 __ fstp_d(FieldOperand(eax, esi, times_4, FixedDoubleArray::kHeaderSize)); | |
7097 } | |
7098 __ jmp(&entry); | |
7099 | |
7100 // Found hole, store hole_nan_as_double instead. | |
7101 __ bind(&convert_hole); | |
7102 if (CpuFeatures::IsSupported(SSE2)) { | |
7103 CpuFeatures::Scope use_sse2(SSE2); | |
7104 __ movdbl(FieldOperand(eax, esi, times_4, FixedDoubleArray::kHeaderSize), | |
7105 the_hole_nan); | |
7106 } else { | |
7107 __ fld_d(Operand::StaticVariable(canonical_the_hole_nan_reference)); | |
7108 __ fstp_d(FieldOperand(eax, esi, times_4, FixedDoubleArray::kHeaderSize)); | |
7109 } | |
7110 | |
7111 __ bind(&entry); | |
7112 __ test(esi, esi); | |
7113 __ j(not_zero, &loop); | |
7114 | |
7115 // Restore necessary values do store. | |
Jakob Kummerow
2011/10/13 09:15:59
I don't understand this comment.
Yang
2011/10/13 09:58:53
Removed and replaced by comments below.
| |
7116 Label done; | |
7117 __ pop(ebx); | |
7118 __ pop(eax); | |
7119 // Set transitioned map. | |
7120 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); | |
7121 __ RecordWriteField(edx, | |
7122 HeapObject::kMapOffset, | |
7123 ebx, | |
7124 edi, | |
7125 kDontSaveFPRegs, | |
7126 EMIT_REMEMBERED_SET, | |
7127 OMIT_SMI_CHECK); | |
7128 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
7129 __ jmp(&done, Label::kNear); | |
7130 | |
7131 __ bind(&gc_required); | |
7132 // Restore esp and esi before jumping into runtime. | |
Jakob Kummerow
2011/10/13 09:15:59
Slightly outdated. s/esp and esi/registers/?
Yang
2011/10/13 09:58:53
Done.
| |
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( | |
Jakob Kummerow
2011/10/13 09:15:59
TODO(jkummerow): continue reviewing here.
| |
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 // edx: receiver | |
Jakob Kummerow
2011/10/13 09:15:59
Again, you can omit comments about registers that
| |
7160 // ebx: length of source FixedDoubleArray (smi-tagged) | |
7161 __ lea(edi, Operand(ebx, times_2, FixedArray::kHeaderSize)); | |
7162 __ AllocateInNewSpace(edi, eax, esi, no_reg, &gc_required, TAG_OBJECT); | |
7163 | |
7164 // eax: destination FixedDoubleArray | |
Jakob Kummerow
2011/10/13 09:15:59
s/FixedDoubleArray/FixedArray/
| |
7165 // ebx: number of elements | |
7166 // edx: receiver | |
7167 // edi: source FixedArray | |
Jakob Kummerow
2011/10/13 09:15:59
Please move this to where it's true. Also, s/Fixed
| |
7168 __ mov(FieldOperand(eax, HeapObject::kMapOffset), | |
7169 Immediate(masm->isolate()->factory()->fixed_array_map())); | |
7170 __ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx); | |
7171 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | |
7172 | |
7173 // Box doubles into heap numbers. | |
7174 // edi: source FixedDoubleArray | |
7175 // eax: destination FixedArray | |
7176 // ebx: index of current element (smi-tagged) | |
Jakob Kummerow
2011/10/13 09:15:59
Move this comment.
| |
7177 __ jmp(&entry); | |
7178 __ bind(&loop); | |
7179 __ sub(ebx, Immediate(Smi::FromInt(1))); | |
7180 uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); | |
7181 __ cmp(FieldOperand(edi, ebx, times_4, offset), Immediate(kHoleNanUpper32)); | |
7182 __ j(equal, &convert_hole); | |
7183 | |
7184 // Non-hole double, copy value into a heap number. | |
7185 __ AllocateHeapNumber(edx, esi, no_reg, &gc_required); | |
7186 // edx: new heap number | |
7187 __ mov(esi, FieldOperand(edi, ebx, times_4, FixedDoubleArray::kHeaderSize)); | |
Jakob Kummerow
2011/10/13 09:15:59
You could check if SSE2 is available and if yes, d
Yang
2011/10/13 09:58:53
Done.
| |
7188 __ mov(FieldOperand(edx, HeapNumber::kValueOffset), esi); | |
7189 __ mov(esi, FieldOperand(edi, ebx, times_4, offset)); | |
7190 __ mov(FieldOperand(edx, HeapNumber::kValueOffset + kPointerSize), esi); | |
7191 __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), edx); | |
7192 __ mov(esi, ebx); | |
7193 __ RecordWriteArray(eax, | |
7194 edx, | |
7195 esi, | |
7196 kDontSaveFPRegs, | |
7197 EMIT_REMEMBERED_SET, | |
7198 OMIT_SMI_CHECK); | |
7199 __ jmp(&entry); | |
7200 | |
7201 // Replace the-hole nan with the-hole pointer. | |
7202 __ bind(&convert_hole); | |
7203 __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize), | |
7204 masm->isolate()->factory()->the_hole_value()); | |
7205 | |
7206 __ bind(&entry); | |
7207 __ test(ebx, ebx); | |
7208 __ j(not_zero, &loop); | |
7209 | |
7210 // Replace receiver's backing store with newly created and filled FixedArray. | |
7211 __ pop(ebx); | |
7212 __ pop(edx); | |
7213 // Set transitioned map. | |
7214 __ mov(FieldOperand(edx, HeapObject::kMapOffset), ebx); | |
7215 __ RecordWriteField(edx, | |
7216 HeapObject::kMapOffset, | |
7217 ebx, | |
7218 edi, | |
7219 kDontSaveFPRegs, | |
7220 EMIT_REMEMBERED_SET, | |
7221 OMIT_SMI_CHECK); | |
7222 __ mov(FieldOperand(edx, JSObject::kElementsOffset), eax); | |
7223 __ mov(ebx, eax); | |
Jakob Kummerow
2011/10/13 09:15:59
This move is unnecessary. EAX is popped next anywa
Yang
2011/10/13 09:58:53
Done.
| |
7224 __ RecordWriteField(edx, | |
7225 JSObject::kElementsOffset, | |
7226 ebx, | |
7227 edi, | |
7228 kDontSaveFPRegs, | |
7229 EMIT_REMEMBERED_SET, | |
7230 OMIT_SMI_CHECK); | |
7231 | |
7232 // Restore registers. | |
7233 Label done; | |
7234 __ pop(eax); | |
7235 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
7236 __ jmp(&done, Label::kNear); | |
7237 | |
7238 __ bind(&gc_required); | |
7239 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | |
7240 __ pop(ebx); | |
7241 __ pop(edx); | |
7242 __ pop(eax); | |
7243 KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode); | |
7244 __ bind(&done); | |
7245 } | |
7246 | |
6995 #undef __ | 7247 #undef __ |
6996 | 7248 |
6997 } } // namespace v8::internal | 7249 } } // namespace v8::internal |
6998 | 7250 |
6999 #endif // V8_TARGET_ARCH_IA32 | 7251 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |