v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
codegen-arm.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
27 
28 #include "v8.h"
29 
30 #if defined(V8_TARGET_ARCH_ARM)
31 
32 #include "codegen.h"
33 #include "macro-assembler.h"
34 
35 namespace v8 {
36 namespace internal {
37 
38 #define __ ACCESS_MASM(masm)
39 
41  switch (type) {
42  case TranscendentalCache::SIN: return &sin;
43  case TranscendentalCache::COS: return &cos;
44  case TranscendentalCache::TAN: return &tan;
45  case TranscendentalCache::LOG: return &log;
46  default: UNIMPLEMENTED();
47  }
48  return NULL;
49 }
50 
51 
53  return &sqrt;
54 }
55 
56 // -------------------------------------------------------------------------
57 // Platform-specific RuntimeCallHelper functions.
58 
59 void StubRuntimeCallHelper::BeforeCall(MacroAssembler* masm) const {
60  masm->EnterFrame(StackFrame::INTERNAL);
61  ASSERT(!masm->has_frame());
62  masm->set_has_frame(true);
63 }
64 
65 
66 void StubRuntimeCallHelper::AfterCall(MacroAssembler* masm) const {
67  masm->LeaveFrame(StackFrame::INTERNAL);
68  ASSERT(masm->has_frame());
69  masm->set_has_frame(false);
70 }
71 
72 
73 // -------------------------------------------------------------------------
74 // Code generators
75 
77  MacroAssembler* masm) {
78  // ----------- S t a t e -------------
79  // -- r0 : value
80  // -- r1 : key
81  // -- r2 : receiver
82  // -- lr : return address
83  // -- r3 : target map, scratch for subsequent call
84  // -- r4 : scratch (elements)
85  // -----------------------------------
86  // Set transitioned map.
88  __ RecordWriteField(r2,
90  r3,
91  r9,
96 }
97 
98 
100  MacroAssembler* masm, Label* fail) {
101  // ----------- S t a t e -------------
102  // -- r0 : value
103  // -- r1 : key
104  // -- r2 : receiver
105  // -- lr : return address
106  // -- r3 : target map, scratch for subsequent call
107  // -- r4 : scratch (elements)
108  // -----------------------------------
109  Label loop, entry, convert_hole, gc_required, only_change_map, done;
110  bool vfp2_supported = CpuFeatures::IsSupported(VFP2);
111 
112  // Check for empty arrays, which only require a map transition and no changes
113  // to the backing store.
115  __ CompareRoot(r4, Heap::kEmptyFixedArrayRootIndex);
116  __ b(eq, &only_change_map);
117 
118  __ push(lr);
120  // r4: source FixedArray
121  // r5: number of elements (smi-tagged)
122 
123  // Allocate new FixedDoubleArray.
124  // Use lr as a temporary register.
125  __ mov(lr, Operand(r5, LSL, 2));
127  __ AllocateInNewSpace(lr, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
128  // r6: destination FixedDoubleArray, not tagged as heap object.
129 
130  // Align the array conveniently for doubles.
131  // Store a filler value in the unused memory.
132  Label aligned, aligned_done;
133  __ tst(r6, Operand(kDoubleAlignmentMask));
134  __ mov(ip, Operand(masm->isolate()->factory()->one_pointer_filler_map()));
135  __ b(eq, &aligned);
136  // Store at the beginning of the allocated memory and update the base pointer.
138  __ b(&aligned_done);
139 
140  __ bind(&aligned);
141  // Store the filler at the end of the allocated memory.
142  __ sub(lr, lr, Operand(kPointerSize));
143  __ str(ip, MemOperand(r6, lr));
144 
145  __ bind(&aligned_done);
146 
147  // Set destination FixedDoubleArray's length and map.
148  __ LoadRoot(r9, Heap::kFixedDoubleArrayMapRootIndex);
150  // Update receiver's map.
152 
154  __ RecordWriteField(r2,
156  r3,
157  r9,
162  // Replace receiver's backing store with newly created FixedDoubleArray.
163  __ add(r3, r6, Operand(kHeapObjectTag));
165  __ RecordWriteField(r2,
167  r3,
168  r9,
173 
174  // Prepare for conversion loop.
175  __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
176  __ add(r7, r6, Operand(FixedDoubleArray::kHeaderSize));
177  __ add(r6, r7, Operand(r5, LSL, 2));
178  __ mov(r4, Operand(kHoleNanLower32));
179  __ mov(r5, Operand(kHoleNanUpper32));
180  // r3: begin of source FixedArray element fields, not tagged
181  // r4: kHoleNanLower32
182  // r5: kHoleNanUpper32
183  // r6: end of destination FixedDoubleArray, not tagged
184  // r7: begin of FixedDoubleArray element fields, not tagged
185  if (!vfp2_supported) __ Push(r1, r0);
186 
187  __ b(&entry);
188 
189  __ bind(&only_change_map);
191  __ RecordWriteField(r2,
193  r3,
194  r9,
199  __ b(&done);
200 
201  // Call into runtime if GC is required.
202  __ bind(&gc_required);
203  __ pop(lr);
204  __ b(fail);
205 
206  // Convert and copy elements.
207  __ bind(&loop);
208  __ ldr(r9, MemOperand(r3, 4, PostIndex));
209  // r9: current element
210  __ UntagAndJumpIfNotSmi(r9, r9, &convert_hole);
211 
212  // Normal smi, convert to double and store.
213  if (vfp2_supported) {
214  CpuFeatures::Scope scope(VFP2);
215  __ vmov(s0, r9);
216  __ vcvt_f64_s32(d0, s0);
217  __ vstr(d0, r7, 0);
218  __ add(r7, r7, Operand(8));
219  } else {
221  r9,
223  d0,
224  r0,
225  r1,
226  lr,
227  s0);
228  __ Strd(r0, r1, MemOperand(r7, 8, PostIndex));
229  }
230  __ b(&entry);
231 
232  // Hole found, store the-hole NaN.
233  __ bind(&convert_hole);
234  if (FLAG_debug_code) {
235  // Restore a "smi-untagged" heap object.
236  __ SmiTag(r9);
237  __ orr(r9, r9, Operand(1));
238  __ CompareRoot(r9, Heap::kTheHoleValueRootIndex);
239  __ Assert(eq, "object found in smi-only array");
240  }
241  __ Strd(r4, r5, MemOperand(r7, 8, PostIndex));
242 
243  __ bind(&entry);
244  __ cmp(r7, r6);
245  __ b(lt, &loop);
246 
247  if (!vfp2_supported) __ Pop(r1, r0);
248  __ pop(lr);
249  __ bind(&done);
250 }
251 
252 
254  MacroAssembler* masm, Label* fail) {
255  // ----------- S t a t e -------------
256  // -- r0 : value
257  // -- r1 : key
258  // -- r2 : receiver
259  // -- lr : return address
260  // -- r3 : target map, scratch for subsequent call
261  // -- r4 : scratch (elements)
262  // -----------------------------------
263  Label entry, loop, convert_hole, gc_required, only_change_map;
264 
265  // Check for empty arrays, which only require a map transition and no changes
266  // to the backing store.
268  __ CompareRoot(r4, Heap::kEmptyFixedArrayRootIndex);
269  __ b(eq, &only_change_map);
270 
271  __ push(lr);
272  __ Push(r3, r2, r1, r0);
274  // r4: source FixedDoubleArray
275  // r5: number of elements (smi-tagged)
276 
277  // Allocate new FixedArray.
278  __ mov(r0, Operand(FixedDoubleArray::kHeaderSize));
279  __ add(r0, r0, Operand(r5, LSL, 1));
280  __ AllocateInNewSpace(r0, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
281  // r6: destination FixedArray, not tagged as heap object
282  // Set destination FixedDoubleArray's length and map.
283  __ LoadRoot(r9, Heap::kFixedArrayMapRootIndex);
286 
287  // Prepare for conversion loop.
288  __ add(r4, r4, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4));
289  __ add(r3, r6, Operand(FixedArray::kHeaderSize));
290  __ add(r6, r6, Operand(kHeapObjectTag));
291  __ add(r5, r3, Operand(r5, LSL, 1));
292  __ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
293  __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
294  // Using offsetted addresses in r4 to fully take advantage of post-indexing.
295  // r3: begin of destination FixedArray element fields, not tagged
296  // r4: begin of source FixedDoubleArray element fields, not tagged, +4
297  // r5: end of destination FixedArray, not tagged
298  // r6: destination FixedArray
299  // r7: the-hole pointer
300  // r9: heap number map
301  __ b(&entry);
302 
303  // Call into runtime if GC is required.
304  __ bind(&gc_required);
305  __ Pop(r3, r2, r1, r0);
306  __ pop(lr);
307  __ b(fail);
308 
309  __ bind(&loop);
310  __ ldr(r1, MemOperand(r4, 8, PostIndex));
311  // lr: current element's upper 32 bit
312  // r4: address of next element's upper 32 bit
313  __ cmp(r1, Operand(kHoleNanUpper32));
314  __ b(eq, &convert_hole);
315 
316  // Non-hole double, copy value into a heap number.
317  __ AllocateHeapNumber(r2, r0, lr, r9, &gc_required);
318  // r2: new heap number
319  __ ldr(r0, MemOperand(r4, 12, NegOffset));
321  __ mov(r0, r3);
322  __ str(r2, MemOperand(r3, 4, PostIndex));
323  __ RecordWrite(r6,
324  r0,
325  r2,
330  __ b(&entry);
331 
332  // Replace the-hole NaN with the-hole pointer.
333  __ bind(&convert_hole);
334  __ str(r7, MemOperand(r3, 4, PostIndex));
335 
336  __ bind(&entry);
337  __ cmp(r3, r5);
338  __ b(lt, &loop);
339 
340  __ Pop(r3, r2, r1, r0);
341  // Replace receiver's backing store with newly created and filled FixedArray.
343  __ RecordWriteField(r2,
345  r6,
346  r9,
351  __ pop(lr);
352 
353  __ bind(&only_change_map);
354  // Update receiver's map.
356  __ RecordWriteField(r2,
358  r3,
359  r9,
364 }
365 
366 
367 void StringCharLoadGenerator::Generate(MacroAssembler* masm,
368  Register string,
369  Register index,
370  Register result,
371  Label* call_runtime) {
372  // Fetch the instance type of the receiver into result register.
373  __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset));
374  __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
375 
376  // We need special handling for indirect strings.
377  Label check_sequential;
378  __ tst(result, Operand(kIsIndirectStringMask));
379  __ b(eq, &check_sequential);
380 
381  // Dispatch on the indirect string shape: slice or cons.
382  Label cons_string;
383  __ tst(result, Operand(kSlicedNotConsMask));
384  __ b(eq, &cons_string);
385 
386  // Handle slices.
387  Label indirect_string_loaded;
388  __ ldr(result, FieldMemOperand(string, SlicedString::kOffsetOffset));
389  __ ldr(string, FieldMemOperand(string, SlicedString::kParentOffset));
390  __ add(index, index, Operand(result, ASR, kSmiTagSize));
391  __ jmp(&indirect_string_loaded);
392 
393  // Handle cons strings.
394  // Check whether the right hand side is the empty string (i.e. if
395  // this is really a flat string in a cons string). If that is not
396  // the case we would rather go to the runtime system now to flatten
397  // the string.
398  __ bind(&cons_string);
399  __ ldr(result, FieldMemOperand(string, ConsString::kSecondOffset));
400  __ CompareRoot(result, Heap::kEmptyStringRootIndex);
401  __ b(ne, call_runtime);
402  // Get the first of the two strings and load its instance type.
403  __ ldr(string, FieldMemOperand(string, ConsString::kFirstOffset));
404 
405  __ bind(&indirect_string_loaded);
406  __ ldr(result, FieldMemOperand(string, HeapObject::kMapOffset));
407  __ ldrb(result, FieldMemOperand(result, Map::kInstanceTypeOffset));
408 
409  // Distinguish sequential and external strings. Only these two string
410  // representations can reach here (slices and flat cons strings have been
411  // reduced to the underlying sequential or external string).
412  Label external_string, check_encoding;
413  __ bind(&check_sequential);
415  __ tst(result, Operand(kStringRepresentationMask));
416  __ b(ne, &external_string);
417 
418  // Prepare sequential strings
420  __ add(string,
421  string,
423  __ jmp(&check_encoding);
424 
425  // Handle external strings.
426  __ bind(&external_string);
427  if (FLAG_debug_code) {
428  // Assert that we do not have a cons or slice (indirect strings) here.
429  // Sequential strings have already been ruled out.
430  __ tst(result, Operand(kIsIndirectStringMask));
431  __ Assert(eq, "external string expected, but not found");
432  }
433  // Rule out short external strings.
435  __ tst(result, Operand(kShortExternalStringMask));
436  __ b(ne, call_runtime);
438 
439  Label ascii, done;
440  __ bind(&check_encoding);
442  __ tst(result, Operand(kStringEncodingMask));
443  __ b(ne, &ascii);
444  // Two-byte string.
445  __ ldrh(result, MemOperand(string, index, LSL, 1));
446  __ jmp(&done);
447  __ bind(&ascii);
448  // Ascii string.
449  __ ldrb(result, MemOperand(string, index));
450  __ bind(&done);
451 }
452 
453 #undef __
454 
455 } } // namespace v8::internal
456 
457 #endif // V8_TARGET_ARCH_ARM
static const int kResourceDataOffset
Definition: objects.h:7747
STATIC_CHECK((kStringRepresentationMask|kStringEncodingMask)==Internals::kFullStringRepresentationMask)
const intptr_t kDoubleAlignmentMask
Definition: v8globals.h:53
const Register r3
const uint32_t kTwoByteStringTag
Definition: objects.h:469
const DwVfpRegister d0
const Register r6
static bool IsSupported(CpuFeature f)
#define ASSERT(condition)
Definition: checks.h:270
virtual void AfterCall(MacroAssembler *masm) const
double(* UnaryMathFunction)(double x)
Definition: codegen.h:90
const uint32_t kStringRepresentationMask
Definition: objects.h:474
const Register r2
const uint32_t kShortExternalStringMask
Definition: objects.h:502
static const int kFirstOffset
Definition: objects.h:7653
static const int kParentOffset
Definition: objects.h:7705
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
static const int kValueOffset
Definition: objects.h:1342
const uint32_t kHoleNanUpper32
Definition: v8globals.h:469
const uint32_t kIsIndirectStringMask
Definition: objects.h:481
const Register ip
const Register r9
const int kPointerSize
Definition: globals.h:220
const int kHeapObjectTag
Definition: v8.h:4009
const uint32_t kHoleNanLower32
Definition: v8globals.h:470
#define __
UnaryMathFunction CreateSqrtFunction()
static void GenerateSmiToDouble(MacroAssembler *masm, Label *fail)
const SwVfpRegister s0
const uint32_t kShortExternalStringTag
Definition: objects.h:503
static void GenerateMapChangeElementsTransition(MacroAssembler *masm)
static void Generate(MacroAssembler *masm, Register string, Register index, Register result, Label *call_runtime)
static const int kHeaderSize
Definition: objects.h:7517
const Register r0
static const int kElementsOffset
Definition: objects.h:2172
static const int kOffsetOffset
Definition: objects.h:7706
static const int kHeaderSize
Definition: objects.h:2296
const Register lr
static const int kMapOffset
Definition: objects.h:1261
const Register r1
static void GenerateDoubleToObject(MacroAssembler *masm, Label *fail)
const uint32_t kSlicedNotConsMask
Definition: objects.h:492
static const int kLengthOffset
Definition: objects.h:2295
static void ConvertIntToDouble(MacroAssembler *masm, Register int_scratch, Destination destination, DwVfpRegister double_dst, Register dst1, Register dst2, Register scratch2, SwVfpRegister single_scratch)
static const int kSecondOffset
Definition: objects.h:7654
MemOperand FieldMemOperand(Register object, int offset)
#define UNIMPLEMENTED()
Definition: checks.h:48
const int kSmiTagSize
Definition: v8.h:4015
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
virtual void BeforeCall(MacroAssembler *masm) const
UnaryMathFunction CreateTranscendentalFunction(TranscendentalCache::Type type)
const Register r5
const uint32_t kStringEncodingMask
Definition: objects.h:468
static const int kInstanceTypeOffset
Definition: objects.h:5158
const Register r4
const Register r7