Chromium Code Reviews| 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 |