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 12 matching lines...) Expand all Loading... |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #if defined(V8_TARGET_ARCH_ARM) | 30 #if defined(V8_TARGET_ARCH_ARM) |
31 | 31 |
32 #include "codegen.h" | 32 #include "codegen.h" |
| 33 #include "macro-assembler.h" |
33 | 34 |
34 namespace v8 { | 35 namespace v8 { |
35 namespace internal { | 36 namespace internal { |
36 | 37 |
| 38 #define __ ACCESS_MASM(masm) |
| 39 |
37 // ------------------------------------------------------------------------- | 40 // ------------------------------------------------------------------------- |
38 // Platform-specific RuntimeCallHelper functions. | 41 // Platform-specific RuntimeCallHelper functions. |
39 | 42 |
40 void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { | 43 void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const { |
41 masm->EnterFrame(StackFrame::INTERNAL); | 44 masm->EnterFrame(StackFrame::INTERNAL); |
42 ASSERT(!masm->has_frame()); | 45 ASSERT(!masm->has_frame()); |
43 masm->set_has_frame(true); | 46 masm->set_has_frame(true); |
44 } | 47 } |
45 | 48 |
46 | 49 |
47 void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { | 50 void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const { |
48 masm->LeaveFrame(StackFrame::INTERNAL); | 51 masm->LeaveFrame(StackFrame::INTERNAL); |
49 ASSERT(masm->has_frame()); | 52 ASSERT(masm->has_frame()); |
50 masm->set_has_frame(false); | 53 masm->set_has_frame(false); |
51 } | 54 } |
52 | 55 |
53 | 56 |
| 57 // ------------------------------------------------------------------------- |
| 58 // Code generators |
| 59 |
| 60 void ElementsTransitionGenerator::GenerateSmiOnlyToObject( |
| 61 MacroAssembler* masm) { |
| 62 // ----------- S t a t e ------------- |
| 63 // -- r0 : value |
| 64 // -- r1 : key |
| 65 // -- r2 : receiver |
| 66 // -- lr : return address |
| 67 // -- r3 : target map, scratch for subsequent call |
| 68 // -- r4 : scratch (elements) |
| 69 // ----------------------------------- |
| 70 // Set transitioned map. |
| 71 __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset)); |
| 72 __ RecordWriteField(r2, |
| 73 HeapObject::kMapOffset, |
| 74 r3, |
| 75 r9, |
| 76 kLRHasNotBeenSaved, |
| 77 kDontSaveFPRegs, |
| 78 EMIT_REMEMBERED_SET, |
| 79 OMIT_SMI_CHECK); |
| 80 } |
| 81 |
| 82 |
| 83 void ElementsTransitionGenerator::GenerateSmiOnlyToDouble( |
| 84 MacroAssembler* masm, Label* fail) { |
| 85 // ----------- S t a t e ------------- |
| 86 // -- r0 : value |
| 87 // -- r1 : key |
| 88 // -- r2 : receiver |
| 89 // -- lr : return address |
| 90 // -- r3 : target map, scratch for subsequent call |
| 91 // -- r4 : scratch (elements) |
| 92 // ----------------------------------- |
| 93 Label loop, entry, convert_hole, gc_required; |
| 94 bool vfp3_supported = CpuFeatures::IsSupported(VFP3); |
| 95 __ push(lr); |
| 96 |
| 97 __ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset)); |
| 98 __ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset)); |
| 99 // r4: source FixedArray |
| 100 // r5: number of elements (smi-tagged) |
| 101 |
| 102 // Allocate new FixedDoubleArray. |
| 103 __ mov(lr, Operand(FixedDoubleArray::kHeaderSize)); |
| 104 __ add(lr, lr, Operand(r5, LSL, 2)); |
| 105 __ AllocateInNewSpace(lr, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS); |
| 106 // r6: destination FixedDoubleArray, not tagged as heap object |
| 107 __ LoadRoot(r9, Heap::kFixedDoubleArrayMapRootIndex); |
| 108 __ str(r9, MemOperand(r6, HeapObject::kMapOffset)); |
| 109 // Set destination FixedDoubleArray's length. |
| 110 __ str(r5, MemOperand(r6, FixedDoubleArray::kLengthOffset)); |
| 111 // Update receiver's map. |
| 112 |
| 113 __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset)); |
| 114 __ RecordWriteField(r2, |
| 115 HeapObject::kMapOffset, |
| 116 r3, |
| 117 r9, |
| 118 kLRHasBeenSaved, |
| 119 kDontSaveFPRegs, |
| 120 EMIT_REMEMBERED_SET, |
| 121 OMIT_SMI_CHECK); |
| 122 // Replace receiver's backing store with newly created FixedDoubleArray. |
| 123 __ add(r3, r6, Operand(kHeapObjectTag)); |
| 124 __ str(r3, FieldMemOperand(r2, JSObject::kElementsOffset)); |
| 125 __ RecordWriteField(r2, |
| 126 JSObject::kElementsOffset, |
| 127 r3, |
| 128 r9, |
| 129 kLRHasBeenSaved, |
| 130 kDontSaveFPRegs, |
| 131 EMIT_REMEMBERED_SET, |
| 132 OMIT_SMI_CHECK); |
| 133 |
| 134 // Prepare for conversion loop. |
| 135 __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 136 __ add(r7, r6, Operand(FixedDoubleArray::kHeaderSize)); |
| 137 __ add(r6, r7, Operand(r5, LSL, 2)); |
| 138 __ mov(r4, Operand(kHoleNanLower32)); |
| 139 __ mov(r5, Operand(kHoleNanUpper32)); |
| 140 // r3: begin of source FixedArray element fields, not tagged |
| 141 // r4: kHoleNanLower32 |
| 142 // r5: kHoleNanUpper32 |
| 143 // r6: end of destination FixedDoubleArray, not tagged |
| 144 // r7: begin of FixedDoubleArray element fields, not tagged |
| 145 if (!vfp3_supported) __ Push(r1, r0); |
| 146 |
| 147 __ b(&entry); |
| 148 |
| 149 // Call into runtime if GC is required. |
| 150 __ bind(&gc_required); |
| 151 __ pop(lr); |
| 152 __ b(fail); |
| 153 |
| 154 // Convert and copy elements. |
| 155 __ bind(&loop); |
| 156 __ ldr(r9, MemOperand(r3, 4, PostIndex)); |
| 157 // r9: current element |
| 158 __ JumpIfNotSmi(r9, &convert_hole); |
| 159 |
| 160 // Normal smi, convert to double and store. |
| 161 __ SmiUntag(r9); |
| 162 if (vfp3_supported) { |
| 163 CpuFeatures::Scope scope(VFP3); |
| 164 __ vmov(s0, r9); |
| 165 __ vcvt_f64_s32(d0, s0); |
| 166 __ vstr(d0, r7, 0); |
| 167 __ add(r7, r7, Operand(8)); |
| 168 } else { |
| 169 FloatingPointHelper::ConvertIntToDouble(masm, |
| 170 r9, |
| 171 FloatingPointHelper::kCoreRegisters, |
| 172 d0, |
| 173 r0, |
| 174 r1, |
| 175 lr, |
| 176 s0); |
| 177 __ Strd(r0, r1, MemOperand(r7, 8, PostIndex)); |
| 178 } |
| 179 __ b(&entry); |
| 180 |
| 181 // Hole found, store the-hole NaN. |
| 182 __ bind(&convert_hole); |
| 183 __ Strd(r4, r5, MemOperand(r7, 8, PostIndex)); |
| 184 |
| 185 __ bind(&entry); |
| 186 __ cmp(r7, r6); |
| 187 __ b(lt, &loop); |
| 188 |
| 189 if (!vfp3_supported) __ Pop(r1, r0); |
| 190 __ pop(lr); |
| 191 } |
| 192 |
| 193 |
| 194 void ElementsTransitionGenerator::GenerateDoubleToObject( |
| 195 MacroAssembler* masm, Label* fail) { |
| 196 // ----------- S t a t e ------------- |
| 197 // -- r0 : value |
| 198 // -- r1 : key |
| 199 // -- r2 : receiver |
| 200 // -- lr : return address |
| 201 // -- r3 : target map, scratch for subsequent call |
| 202 // -- r4 : scratch (elements) |
| 203 // ----------------------------------- |
| 204 Label entry, loop, convert_hole, gc_required; |
| 205 |
| 206 __ push(lr); |
| 207 __ Push(r3, r2, r1, r0); |
| 208 |
| 209 __ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset)); |
| 210 __ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset)); |
| 211 // r4: source FixedDoubleArray |
| 212 // r5: number of elements (smi-tagged) |
| 213 |
| 214 // Allocate new FixedArray. |
| 215 __ mov(r0, Operand(FixedDoubleArray::kHeaderSize)); |
| 216 __ add(r0, r0, Operand(r5, LSL, 1)); |
| 217 __ AllocateInNewSpace(r0, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS); |
| 218 // r6: destination FixedArray, not tagged as heap object |
| 219 __ LoadRoot(r9, Heap::kFixedArrayMapRootIndex); |
| 220 __ str(r9, MemOperand(r6, HeapObject::kMapOffset)); |
| 221 // Set destination FixedDoubleArray's length. |
| 222 __ str(r5, MemOperand(r6, FixedDoubleArray::kLengthOffset)); |
| 223 |
| 224 // Prepare for conversion loop. |
| 225 __ add(r4, r4, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4)); |
| 226 __ add(r3, r6, Operand(FixedArray::kHeaderSize)); |
| 227 __ add(r6, r6, Operand(kHeapObjectTag)); |
| 228 __ add(r5, r3, Operand(r5, LSL, 1)); |
| 229 __ LoadRoot(r7, Heap::kTheHoleValueRootIndex); |
| 230 __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex); |
| 231 // Using offsetted addresses in r4 to fully take advantage of post-indexing. |
| 232 // r3: begin of destination FixedArray element fields, not tagged |
| 233 // r4: begin of source FixedDoubleArray element fields, not tagged, +4 |
| 234 // r5: end of destination FixedArray, not tagged |
| 235 // r6: destination FixedArray |
| 236 // r7: the-hole pointer |
| 237 // r9: heap number map |
| 238 __ b(&entry); |
| 239 |
| 240 // Call into runtime if GC is required. |
| 241 __ bind(&gc_required); |
| 242 __ Pop(r3, r2, r1, r0); |
| 243 __ pop(lr); |
| 244 __ b(fail); |
| 245 |
| 246 __ bind(&loop); |
| 247 __ ldr(r1, MemOperand(r4, 8, PostIndex)); |
| 248 // lr: current element's upper 32 bit |
| 249 // r4: address of next element's upper 32 bit |
| 250 __ cmp(r1, Operand(kHoleNanUpper32)); |
| 251 __ b(eq, &convert_hole); |
| 252 |
| 253 // Non-hole double, copy value into a heap number. |
| 254 __ AllocateHeapNumber(r2, r0, lr, r9, &gc_required); |
| 255 // r2: new heap number |
| 256 __ ldr(r0, MemOperand(r4, 12, NegOffset)); |
| 257 __ Strd(r0, r1, FieldMemOperand(r2, HeapNumber::kValueOffset)); |
| 258 __ mov(r0, r3); |
| 259 __ str(r2, MemOperand(r3, 4, PostIndex)); |
| 260 __ RecordWrite(r6, |
| 261 r0, |
| 262 r2, |
| 263 kLRHasBeenSaved, |
| 264 kDontSaveFPRegs, |
| 265 EMIT_REMEMBERED_SET, |
| 266 OMIT_SMI_CHECK); |
| 267 __ b(&entry); |
| 268 |
| 269 // Replace the-hole NaN with the-hole pointer. |
| 270 __ bind(&convert_hole); |
| 271 __ str(r7, MemOperand(r3, 4, PostIndex)); |
| 272 |
| 273 __ bind(&entry); |
| 274 __ cmp(r3, r5); |
| 275 __ b(lt, &loop); |
| 276 |
| 277 __ Pop(r3, r2, r1, r0); |
| 278 // Update receiver's map. |
| 279 __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset)); |
| 280 __ RecordWriteField(r2, |
| 281 HeapObject::kMapOffset, |
| 282 r3, |
| 283 r9, |
| 284 kLRHasBeenSaved, |
| 285 kDontSaveFPRegs, |
| 286 EMIT_REMEMBERED_SET, |
| 287 OMIT_SMI_CHECK); |
| 288 // Replace receiver's backing store with newly created and filled FixedArray. |
| 289 __ str(r6, FieldMemOperand(r2, JSObject::kElementsOffset)); |
| 290 __ RecordWriteField(r2, |
| 291 JSObject::kElementsOffset, |
| 292 r6, |
| 293 r9, |
| 294 kLRHasBeenSaved, |
| 295 kDontSaveFPRegs, |
| 296 EMIT_REMEMBERED_SET, |
| 297 OMIT_SMI_CHECK); |
| 298 __ pop(lr); |
| 299 } |
| 300 |
| 301 #undef __ |
| 302 |
54 } } // namespace v8::internal | 303 } } // namespace v8::internal |
55 | 304 |
56 #endif // V8_TARGET_ARCH_ARM | 305 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |