The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / arm / code-stubs-arm.h @ f230a1cf

History | View | Annotate | Download (18.3 KB)

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
#ifndef V8_ARM_CODE_STUBS_ARM_H_
29
#define V8_ARM_CODE_STUBS_ARM_H_
30

    
31
#include "ic-inl.h"
32

    
33
namespace v8 {
34
namespace internal {
35

    
36

    
37
void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code);
38

    
39

    
40
// Compute a transcendental math function natively, or call the
41
// TranscendentalCache runtime function.
42
class TranscendentalCacheStub: public PlatformCodeStub {
43
 public:
44
  enum ArgumentType {
45
    TAGGED = 0 << TranscendentalCache::kTranscendentalTypeBits,
46
    UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
47
  };
48

    
49
  TranscendentalCacheStub(TranscendentalCache::Type type,
50
                          ArgumentType argument_type)
51
      : type_(type), argument_type_(argument_type) { }
52
  void Generate(MacroAssembler* masm);
53
 private:
54
  TranscendentalCache::Type type_;
55
  ArgumentType argument_type_;
56
  void GenerateCallCFunction(MacroAssembler* masm, Register scratch);
57

    
58
  Major MajorKey() { return TranscendentalCache; }
59
  int MinorKey() { return type_ | argument_type_; }
60
  Runtime::FunctionId RuntimeFunction();
61
};
62

    
63

    
64
class StoreBufferOverflowStub: public PlatformCodeStub {
65
 public:
66
  explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp)
67
      : save_doubles_(save_fp) {}
68

    
69
  void Generate(MacroAssembler* masm);
70

    
71
  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE { return true; }
72
  static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
73
  virtual bool SometimesSetsUpAFrame() { return false; }
74

    
75
 private:
76
  SaveFPRegsMode save_doubles_;
77

    
78
  Major MajorKey() { return StoreBufferOverflow; }
79
  int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; }
80
};
81

    
82

    
83
class StringHelper : public AllStatic {
84
 public:
85
  // Generate code for copying characters using a simple loop. This should only
86
  // be used in places where the number of characters is small and the
87
  // additional setup and checking in GenerateCopyCharactersLong adds too much
88
  // overhead. Copying of overlapping regions is not supported.
89
  // Dest register ends at the position after the last character written.
90
  static void GenerateCopyCharacters(MacroAssembler* masm,
91
                                     Register dest,
92
                                     Register src,
93
                                     Register count,
94
                                     Register scratch,
95
                                     bool ascii);
96

    
97
  // Generate code for copying a large number of characters. This function
98
  // is allowed to spend extra time setting up conditions to make copying
99
  // faster. Copying of overlapping regions is not supported.
100
  // Dest register ends at the position after the last character written.
101
  static void GenerateCopyCharactersLong(MacroAssembler* masm,
102
                                         Register dest,
103
                                         Register src,
104
                                         Register count,
105
                                         Register scratch1,
106
                                         Register scratch2,
107
                                         Register scratch3,
108
                                         Register scratch4,
109
                                         int flags);
110

    
111

    
112
  // Probe the string table for a two character string. If the string is
113
  // not found by probing a jump to the label not_found is performed. This jump
114
  // does not guarantee that the string is not in the string table. If the
115
  // string is found the code falls through with the string in register r0.
116
  // Contents of both c1 and c2 registers are modified. At the exit c1 is
117
  // guaranteed to contain halfword with low and high bytes equal to
118
  // initial contents of c1 and c2 respectively.
119
  static void GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
120
                                                   Register c1,
121
                                                   Register c2,
122
                                                   Register scratch1,
123
                                                   Register scratch2,
124
                                                   Register scratch3,
125
                                                   Register scratch4,
126
                                                   Register scratch5,
127
                                                   Label* not_found);
128

    
129
  // Generate string hash.
130
  static void GenerateHashInit(MacroAssembler* masm,
131
                               Register hash,
132
                               Register character);
133

    
134
  static void GenerateHashAddCharacter(MacroAssembler* masm,
135
                                       Register hash,
136
                                       Register character);
137

    
138
  static void GenerateHashGetHash(MacroAssembler* masm,
139
                                  Register hash);
140

    
141
 private:
142
  DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
143
};
144

    
145

    
146
class StringAddStub: public PlatformCodeStub {
147
 public:
148
  explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
149

    
150
 private:
151
  Major MajorKey() { return StringAdd; }
152
  int MinorKey() { return flags_; }
153

    
154
  void Generate(MacroAssembler* masm);
155

    
156
  void GenerateConvertArgument(MacroAssembler* masm,
157
                               int stack_offset,
158
                               Register arg,
159
                               Register scratch1,
160
                               Register scratch2,
161
                               Register scratch3,
162
                               Register scratch4,
163
                               Label* slow);
164

    
165
  void GenerateRegisterArgsPush(MacroAssembler* masm);
166
  void GenerateRegisterArgsPop(MacroAssembler* masm);
167

    
168
  const StringAddFlags flags_;
169
};
170

    
171

    
172
class SubStringStub: public PlatformCodeStub {
173
 public:
174
  SubStringStub() {}
175

    
176
 private:
177
  Major MajorKey() { return SubString; }
178
  int MinorKey() { return 0; }
179

    
180
  void Generate(MacroAssembler* masm);
181
};
182

    
183

    
184

    
185
class StringCompareStub: public PlatformCodeStub {
186
 public:
187
  StringCompareStub() { }
188

    
189
  // Compares two flat ASCII strings and returns result in r0.
190
  static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
191
                                              Register left,
192
                                              Register right,
193
                                              Register scratch1,
194
                                              Register scratch2,
195
                                              Register scratch3,
196
                                              Register scratch4);
197

    
198
  // Compares two flat ASCII strings for equality and returns result
199
  // in r0.
200
  static void GenerateFlatAsciiStringEquals(MacroAssembler* masm,
201
                                            Register left,
202
                                            Register right,
203
                                            Register scratch1,
204
                                            Register scratch2,
205
                                            Register scratch3);
206

    
207
 private:
208
  virtual Major MajorKey() { return StringCompare; }
209
  virtual int MinorKey() { return 0; }
210
  virtual void Generate(MacroAssembler* masm);
211

    
212
  static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm,
213
                                            Register left,
214
                                            Register right,
215
                                            Register length,
216
                                            Register scratch1,
217
                                            Register scratch2,
218
                                            Label* chars_not_equal);
219
};
220

    
221

    
222
// This stub can convert a signed int32 to a heap number (double).  It does
223
// not work for int32s that are in Smi range!  No GC occurs during this stub
224
// so you don't have to set up the frame.
225
class WriteInt32ToHeapNumberStub : public PlatformCodeStub {
226
 public:
227
  WriteInt32ToHeapNumberStub(Register the_int,
228
                             Register the_heap_number,
229
                             Register scratch)
230
      : the_int_(the_int),
231
        the_heap_number_(the_heap_number),
232
        scratch_(scratch) { }
233

    
234
  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
235
  static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
236

    
237
 private:
238
  Register the_int_;
239
  Register the_heap_number_;
240
  Register scratch_;
241

    
242
  // Minor key encoding in 16 bits.
243
  class IntRegisterBits: public BitField<int, 0, 4> {};
244
  class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
245
  class ScratchRegisterBits: public BitField<int, 8, 4> {};
246

    
247
  Major MajorKey() { return WriteInt32ToHeapNumber; }
248
  int MinorKey() {
249
    // Encode the parameters in a unique 16 bit value.
250
    return IntRegisterBits::encode(the_int_.code())
251
           | HeapNumberRegisterBits::encode(the_heap_number_.code())
252
           | ScratchRegisterBits::encode(scratch_.code());
253
  }
254

    
255
  void Generate(MacroAssembler* masm);
256
};
257

    
258

    
259
class RecordWriteStub: public PlatformCodeStub {
260
 public:
261
  RecordWriteStub(Register object,
262
                  Register value,
263
                  Register address,
264
                  RememberedSetAction remembered_set_action,
265
                  SaveFPRegsMode fp_mode)
266
      : object_(object),
267
        value_(value),
268
        address_(address),
269
        remembered_set_action_(remembered_set_action),
270
        save_fp_regs_mode_(fp_mode),
271
        regs_(object,   // An input reg.
272
              address,  // An input reg.
273
              value) {  // One scratch reg.
274
  }
275

    
276
  enum Mode {
277
    STORE_BUFFER_ONLY,
278
    INCREMENTAL,
279
    INCREMENTAL_COMPACTION
280
  };
281

    
282
  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
283
  static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
284
  virtual bool SometimesSetsUpAFrame() { return false; }
285

    
286
  static void PatchBranchIntoNop(MacroAssembler* masm, int pos) {
287
    masm->instr_at_put(pos, (masm->instr_at(pos) & ~B27) | (B24 | B20));
288
    ASSERT(Assembler::IsTstImmediate(masm->instr_at(pos)));
289
  }
290

    
291
  static void PatchNopIntoBranch(MacroAssembler* masm, int pos) {
292
    masm->instr_at_put(pos, (masm->instr_at(pos) & ~(B24 | B20)) | B27);
293
    ASSERT(Assembler::IsBranch(masm->instr_at(pos)));
294
  }
295

    
296
  static Mode GetMode(Code* stub) {
297
    Instr first_instruction = Assembler::instr_at(stub->instruction_start());
298
    Instr second_instruction = Assembler::instr_at(stub->instruction_start() +
299
                                                   Assembler::kInstrSize);
300

    
301
    if (Assembler::IsBranch(first_instruction)) {
302
      return INCREMENTAL;
303
    }
304

    
305
    ASSERT(Assembler::IsTstImmediate(first_instruction));
306

    
307
    if (Assembler::IsBranch(second_instruction)) {
308
      return INCREMENTAL_COMPACTION;
309
    }
310

    
311
    ASSERT(Assembler::IsTstImmediate(second_instruction));
312

    
313
    return STORE_BUFFER_ONLY;
314
  }
315

    
316
  static void Patch(Code* stub, Mode mode) {
317
    MacroAssembler masm(NULL,
318
                        stub->instruction_start(),
319
                        stub->instruction_size());
320
    switch (mode) {
321
      case STORE_BUFFER_ONLY:
322
        ASSERT(GetMode(stub) == INCREMENTAL ||
323
               GetMode(stub) == INCREMENTAL_COMPACTION);
324
        PatchBranchIntoNop(&masm, 0);
325
        PatchBranchIntoNop(&masm, Assembler::kInstrSize);
326
        break;
327
      case INCREMENTAL:
328
        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
329
        PatchNopIntoBranch(&masm, 0);
330
        break;
331
      case INCREMENTAL_COMPACTION:
332
        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
333
        PatchNopIntoBranch(&masm, Assembler::kInstrSize);
334
        break;
335
    }
336
    ASSERT(GetMode(stub) == mode);
337
    CPU::FlushICache(stub->instruction_start(), 2 * Assembler::kInstrSize);
338
  }
339

    
340
 private:
341
  // This is a helper class for freeing up 3 scratch registers.  The input is
342
  // two registers that must be preserved and one scratch register provided by
343
  // the caller.
344
  class RegisterAllocation {
345
   public:
346
    RegisterAllocation(Register object,
347
                       Register address,
348
                       Register scratch0)
349
        : object_(object),
350
          address_(address),
351
          scratch0_(scratch0) {
352
      ASSERT(!AreAliased(scratch0, object, address, no_reg));
353
      scratch1_ = GetRegisterThatIsNotOneOf(object_, address_, scratch0_);
354
    }
355

    
356
    void Save(MacroAssembler* masm) {
357
      ASSERT(!AreAliased(object_, address_, scratch1_, scratch0_));
358
      // We don't have to save scratch0_ because it was given to us as
359
      // a scratch register.
360
      masm->push(scratch1_);
361
    }
362

    
363
    void Restore(MacroAssembler* masm) {
364
      masm->pop(scratch1_);
365
    }
366

    
367
    // If we have to call into C then we need to save and restore all caller-
368
    // saved registers that were not already preserved.  The scratch registers
369
    // will be restored by other means so we don't bother pushing them here.
370
    void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
371
      masm->stm(db_w, sp, (kCallerSaved | lr.bit()) & ~scratch1_.bit());
372
      if (mode == kSaveFPRegs) {
373
        masm->SaveFPRegs(sp, scratch0_);
374
      }
375
    }
376

    
377
    inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
378
                                           SaveFPRegsMode mode) {
379
      if (mode == kSaveFPRegs) {
380
        masm->RestoreFPRegs(sp, scratch0_);
381
      }
382
      masm->ldm(ia_w, sp, (kCallerSaved | lr.bit()) & ~scratch1_.bit());
383
    }
384

    
385
    inline Register object() { return object_; }
386
    inline Register address() { return address_; }
387
    inline Register scratch0() { return scratch0_; }
388
    inline Register scratch1() { return scratch1_; }
389

    
390
   private:
391
    Register object_;
392
    Register address_;
393
    Register scratch0_;
394
    Register scratch1_;
395

    
396
    friend class RecordWriteStub;
397
  };
398

    
399
  enum OnNoNeedToInformIncrementalMarker {
400
    kReturnOnNoNeedToInformIncrementalMarker,
401
    kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
402
  };
403

    
404
  void Generate(MacroAssembler* masm);
405
  void GenerateIncremental(MacroAssembler* masm, Mode mode);
406
  void CheckNeedsToInformIncrementalMarker(
407
      MacroAssembler* masm,
408
      OnNoNeedToInformIncrementalMarker on_no_need,
409
      Mode mode);
410
  void InformIncrementalMarker(MacroAssembler* masm, Mode mode);
411

    
412
  Major MajorKey() { return RecordWrite; }
413

    
414
  int MinorKey() {
415
    return ObjectBits::encode(object_.code()) |
416
        ValueBits::encode(value_.code()) |
417
        AddressBits::encode(address_.code()) |
418
        RememberedSetActionBits::encode(remembered_set_action_) |
419
        SaveFPRegsModeBits::encode(save_fp_regs_mode_);
420
  }
421

    
422
  void Activate(Code* code) {
423
    code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
424
  }
425

    
426
  class ObjectBits: public BitField<int, 0, 4> {};
427
  class ValueBits: public BitField<int, 4, 4> {};
428
  class AddressBits: public BitField<int, 8, 4> {};
429
  class RememberedSetActionBits: public BitField<RememberedSetAction, 12, 1> {};
430
  class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 13, 1> {};
431

    
432
  Register object_;
433
  Register value_;
434
  Register address_;
435
  RememberedSetAction remembered_set_action_;
436
  SaveFPRegsMode save_fp_regs_mode_;
437
  Label slow_;
438
  RegisterAllocation regs_;
439
};
440

    
441

    
442
// Trampoline stub to call into native code. To call safely into native code
443
// in the presence of compacting GC (which can move code objects) we need to
444
// keep the code which called into native pinned in the memory. Currently the
445
// simplest approach is to generate such stub early enough so it can never be
446
// moved by GC
447
class DirectCEntryStub: public PlatformCodeStub {
448
 public:
449
  DirectCEntryStub() {}
450
  void Generate(MacroAssembler* masm);
451
  void GenerateCall(MacroAssembler* masm, Register target);
452

    
453
 private:
454
  Major MajorKey() { return DirectCEntry; }
455
  int MinorKey() { return 0; }
456

    
457
  bool NeedsImmovableCode() { return true; }
458
};
459

    
460

    
461
class NameDictionaryLookupStub: public PlatformCodeStub {
462
 public:
463
  enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
464

    
465
  explicit NameDictionaryLookupStub(LookupMode mode) : mode_(mode) { }
466

    
467
  void Generate(MacroAssembler* masm);
468

    
469
  static void GenerateNegativeLookup(MacroAssembler* masm,
470
                                     Label* miss,
471
                                     Label* done,
472
                                     Register receiver,
473
                                     Register properties,
474
                                     Handle<Name> name,
475
                                     Register scratch0);
476

    
477
  static void GeneratePositiveLookup(MacroAssembler* masm,
478
                                     Label* miss,
479
                                     Label* done,
480
                                     Register elements,
481
                                     Register name,
482
                                     Register r0,
483
                                     Register r1);
484

    
485
  virtual bool SometimesSetsUpAFrame() { return false; }
486

    
487
 private:
488
  static const int kInlinedProbes = 4;
489
  static const int kTotalProbes = 20;
490

    
491
  static const int kCapacityOffset =
492
      NameDictionary::kHeaderSize +
493
      NameDictionary::kCapacityIndex * kPointerSize;
494

    
495
  static const int kElementsStartOffset =
496
      NameDictionary::kHeaderSize +
497
      NameDictionary::kElementsStartIndex * kPointerSize;
498

    
499
  Major MajorKey() { return NameDictionaryLookup; }
500

    
501
  int MinorKey() {
502
    return LookupModeBits::encode(mode_);
503
  }
504

    
505
  class LookupModeBits: public BitField<LookupMode, 0, 1> {};
506

    
507
  LookupMode mode_;
508
};
509

    
510

    
511
} }  // namespace v8::internal
512

    
513
#endif  // V8_ARM_CODE_STUBS_ARM_H_