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 / mips / code-stubs-mips.h @ f230a1cf

History | View | Annotate | Download (19.1 KB)

1
// Copyright 2011 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_MIPS_CODE_STUBS_ARM_H_
29
#define V8_MIPS_CODE_STUBS_ARM_H_
30

    
31
#include "ic-inl.h"
32

    
33

    
34
namespace v8 {
35
namespace internal {
36

    
37

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

    
40

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

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

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

    
64

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

    
70
  void Generate(MacroAssembler* masm);
71

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

    
76
 private:
77
  SaveFPRegsMode save_doubles_;
78

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

    
83

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

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

    
113

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

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

    
136
  static void GenerateHashAddCharacter(MacroAssembler* masm,
137
                                       Register hash,
138
                                       Register character);
139

    
140
  static void GenerateHashGetHash(MacroAssembler* masm,
141
                                  Register hash);
142

    
143
 private:
144
  DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
145
};
146

    
147

    
148
class StringAddStub: public PlatformCodeStub {
149
 public:
150
  explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
151

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

    
156
  void Generate(MacroAssembler* masm);
157

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

    
167
  void GenerateRegisterArgsPush(MacroAssembler* masm);
168
  void GenerateRegisterArgsPop(MacroAssembler* masm);
169

    
170
  const StringAddFlags flags_;
171
};
172

    
173

    
174
class SubStringStub: public PlatformCodeStub {
175
 public:
176
  SubStringStub() {}
177

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

    
182
  void Generate(MacroAssembler* masm);
183
};
184

    
185

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

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

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

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

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

    
223

    
224
// This stub can convert a signed int32 to a heap number (double).  It does
225
// not work for int32s that are in Smi range!  No GC occurs during this stub
226
// so you don't have to set up the frame.
227
class WriteInt32ToHeapNumberStub : public PlatformCodeStub {
228
 public:
229
  WriteInt32ToHeapNumberStub(Register the_int,
230
                             Register the_heap_number,
231
                             Register scratch,
232
                             Register scratch2)
233
      : the_int_(the_int),
234
        the_heap_number_(the_heap_number),
235
        scratch_(scratch),
236
        sign_(scratch2) {
237
    ASSERT(IntRegisterBits::is_valid(the_int_.code()));
238
    ASSERT(HeapNumberRegisterBits::is_valid(the_heap_number_.code()));
239
    ASSERT(ScratchRegisterBits::is_valid(scratch_.code()));
240
    ASSERT(SignRegisterBits::is_valid(sign_.code()));
241
  }
242

    
243
  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
244
  static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
245

    
246
 private:
247
  Register the_int_;
248
  Register the_heap_number_;
249
  Register scratch_;
250
  Register sign_;
251

    
252
  // Minor key encoding in 16 bits.
253
  class IntRegisterBits: public BitField<int, 0, 4> {};
254
  class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
255
  class ScratchRegisterBits: public BitField<int, 8, 4> {};
256
  class SignRegisterBits: public BitField<int, 12, 4> {};
257

    
258
  Major MajorKey() { return WriteInt32ToHeapNumber; }
259
  int MinorKey() {
260
    // Encode the parameters in a unique 16 bit value.
261
    return IntRegisterBits::encode(the_int_.code())
262
           | HeapNumberRegisterBits::encode(the_heap_number_.code())
263
           | ScratchRegisterBits::encode(scratch_.code())
264
           | SignRegisterBits::encode(sign_.code());
265
  }
266

    
267
  void Generate(MacroAssembler* masm);
268
};
269

    
270

    
271
class RecordWriteStub: public PlatformCodeStub {
272
 public:
273
  RecordWriteStub(Register object,
274
                  Register value,
275
                  Register address,
276
                  RememberedSetAction remembered_set_action,
277
                  SaveFPRegsMode fp_mode)
278
      : object_(object),
279
        value_(value),
280
        address_(address),
281
        remembered_set_action_(remembered_set_action),
282
        save_fp_regs_mode_(fp_mode),
283
        regs_(object,   // An input reg.
284
              address,  // An input reg.
285
              value) {  // One scratch reg.
286
  }
287

    
288
  enum Mode {
289
    STORE_BUFFER_ONLY,
290
    INCREMENTAL,
291
    INCREMENTAL_COMPACTION
292
  };
293

    
294
  virtual bool IsPregenerated(Isolate* isolate) V8_OVERRIDE;
295
  static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
296
  virtual bool SometimesSetsUpAFrame() { return false; }
297

    
298
  static void PatchBranchIntoNop(MacroAssembler* masm, int pos) {
299
    const unsigned offset = masm->instr_at(pos) & kImm16Mask;
300
    masm->instr_at_put(pos, BNE | (zero_reg.code() << kRsShift) |
301
        (zero_reg.code() << kRtShift) | (offset & kImm16Mask));
302
    ASSERT(Assembler::IsBne(masm->instr_at(pos)));
303
  }
304

    
305
  static void PatchNopIntoBranch(MacroAssembler* masm, int pos) {
306
    const unsigned offset = masm->instr_at(pos) & kImm16Mask;
307
    masm->instr_at_put(pos, BEQ | (zero_reg.code() << kRsShift) |
308
        (zero_reg.code() << kRtShift) | (offset & kImm16Mask));
309
    ASSERT(Assembler::IsBeq(masm->instr_at(pos)));
310
  }
311

    
312
  static Mode GetMode(Code* stub) {
313
    Instr first_instruction = Assembler::instr_at(stub->instruction_start());
314
    Instr second_instruction = Assembler::instr_at(stub->instruction_start() +
315
                                                   2 * Assembler::kInstrSize);
316

    
317
    if (Assembler::IsBeq(first_instruction)) {
318
      return INCREMENTAL;
319
    }
320

    
321
    ASSERT(Assembler::IsBne(first_instruction));
322

    
323
    if (Assembler::IsBeq(second_instruction)) {
324
      return INCREMENTAL_COMPACTION;
325
    }
326

    
327
    ASSERT(Assembler::IsBne(second_instruction));
328

    
329
    return STORE_BUFFER_ONLY;
330
  }
331

    
332
  static void Patch(Code* stub, Mode mode) {
333
    MacroAssembler masm(NULL,
334
                        stub->instruction_start(),
335
                        stub->instruction_size());
336
    switch (mode) {
337
      case STORE_BUFFER_ONLY:
338
        ASSERT(GetMode(stub) == INCREMENTAL ||
339
               GetMode(stub) == INCREMENTAL_COMPACTION);
340
        PatchBranchIntoNop(&masm, 0);
341
        PatchBranchIntoNop(&masm, 2 * Assembler::kInstrSize);
342
        break;
343
      case INCREMENTAL:
344
        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
345
        PatchNopIntoBranch(&masm, 0);
346
        break;
347
      case INCREMENTAL_COMPACTION:
348
        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
349
        PatchNopIntoBranch(&masm, 2 * Assembler::kInstrSize);
350
        break;
351
    }
352
    ASSERT(GetMode(stub) == mode);
353
    CPU::FlushICache(stub->instruction_start(), 4 * Assembler::kInstrSize);
354
  }
355

    
356
 private:
357
  // This is a helper class for freeing up 3 scratch registers.  The input is
358
  // two registers that must be preserved and one scratch register provided by
359
  // the caller.
360
  class RegisterAllocation {
361
   public:
362
    RegisterAllocation(Register object,
363
                       Register address,
364
                       Register scratch0)
365
        : object_(object),
366
          address_(address),
367
          scratch0_(scratch0) {
368
      ASSERT(!AreAliased(scratch0, object, address, no_reg));
369
      scratch1_ = GetRegisterThatIsNotOneOf(object_, address_, scratch0_);
370
    }
371

    
372
    void Save(MacroAssembler* masm) {
373
      ASSERT(!AreAliased(object_, address_, scratch1_, scratch0_));
374
      // We don't have to save scratch0_ because it was given to us as
375
      // a scratch register.
376
      masm->push(scratch1_);
377
    }
378

    
379
    void Restore(MacroAssembler* masm) {
380
      masm->pop(scratch1_);
381
    }
382

    
383
    // If we have to call into C then we need to save and restore all caller-
384
    // saved registers that were not already preserved.  The scratch registers
385
    // will be restored by other means so we don't bother pushing them here.
386
    void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
387
      masm->MultiPush((kJSCallerSaved | ra.bit()) & ~scratch1_.bit());
388
      if (mode == kSaveFPRegs) {
389
        masm->MultiPushFPU(kCallerSavedFPU);
390
      }
391
    }
392

    
393
    inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
394
                                           SaveFPRegsMode mode) {
395
      if (mode == kSaveFPRegs) {
396
        masm->MultiPopFPU(kCallerSavedFPU);
397
      }
398
      masm->MultiPop((kJSCallerSaved | ra.bit()) & ~scratch1_.bit());
399
    }
400

    
401
    inline Register object() { return object_; }
402
    inline Register address() { return address_; }
403
    inline Register scratch0() { return scratch0_; }
404
    inline Register scratch1() { return scratch1_; }
405

    
406
   private:
407
    Register object_;
408
    Register address_;
409
    Register scratch0_;
410
    Register scratch1_;
411

    
412
    friend class RecordWriteStub;
413
  };
414

    
415
  enum OnNoNeedToInformIncrementalMarker {
416
    kReturnOnNoNeedToInformIncrementalMarker,
417
    kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
418
  };
419

    
420
  void Generate(MacroAssembler* masm);
421
  void GenerateIncremental(MacroAssembler* masm, Mode mode);
422
  void CheckNeedsToInformIncrementalMarker(
423
      MacroAssembler* masm,
424
      OnNoNeedToInformIncrementalMarker on_no_need,
425
      Mode mode);
426
  void InformIncrementalMarker(MacroAssembler* masm, Mode mode);
427

    
428
  Major MajorKey() { return RecordWrite; }
429

    
430
  int MinorKey() {
431
    return ObjectBits::encode(object_.code()) |
432
        ValueBits::encode(value_.code()) |
433
        AddressBits::encode(address_.code()) |
434
        RememberedSetActionBits::encode(remembered_set_action_) |
435
        SaveFPRegsModeBits::encode(save_fp_regs_mode_);
436
  }
437

    
438
  void Activate(Code* code) {
439
    code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
440
  }
441

    
442
  class ObjectBits: public BitField<int, 0, 5> {};
443
  class ValueBits: public BitField<int, 5, 5> {};
444
  class AddressBits: public BitField<int, 10, 5> {};
445
  class RememberedSetActionBits: public BitField<RememberedSetAction, 15, 1> {};
446
  class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 16, 1> {};
447

    
448
  Register object_;
449
  Register value_;
450
  Register address_;
451
  RememberedSetAction remembered_set_action_;
452
  SaveFPRegsMode save_fp_regs_mode_;
453
  Label slow_;
454
  RegisterAllocation regs_;
455
};
456

    
457

    
458
// Trampoline stub to call into native code. To call safely into native code
459
// in the presence of compacting GC (which can move code objects) we need to
460
// keep the code which called into native pinned in the memory. Currently the
461
// simplest approach is to generate such stub early enough so it can never be
462
// moved by GC
463
class DirectCEntryStub: public PlatformCodeStub {
464
 public:
465
  DirectCEntryStub() {}
466
  void Generate(MacroAssembler* masm);
467
  void GenerateCall(MacroAssembler* masm, Register target);
468

    
469
 private:
470
  Major MajorKey() { return DirectCEntry; }
471
  int MinorKey() { return 0; }
472

    
473
  bool NeedsImmovableCode() { return true; }
474
};
475

    
476

    
477
class NameDictionaryLookupStub: public PlatformCodeStub {
478
 public:
479
  enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
480

    
481
  explicit NameDictionaryLookupStub(LookupMode mode) : mode_(mode) { }
482

    
483
  void Generate(MacroAssembler* masm);
484

    
485
  static void GenerateNegativeLookup(MacroAssembler* masm,
486
                                     Label* miss,
487
                                     Label* done,
488
                                     Register receiver,
489
                                     Register properties,
490
                                     Handle<Name> name,
491
                                     Register scratch0);
492

    
493
  static void GeneratePositiveLookup(MacroAssembler* masm,
494
                                     Label* miss,
495
                                     Label* done,
496
                                     Register elements,
497
                                     Register name,
498
                                     Register r0,
499
                                     Register r1);
500

    
501
  virtual bool SometimesSetsUpAFrame() { return false; }
502

    
503
 private:
504
  static const int kInlinedProbes = 4;
505
  static const int kTotalProbes = 20;
506

    
507
  static const int kCapacityOffset =
508
      NameDictionary::kHeaderSize +
509
      NameDictionary::kCapacityIndex * kPointerSize;
510

    
511
  static const int kElementsStartOffset =
512
      NameDictionary::kHeaderSize +
513
      NameDictionary::kElementsStartIndex * kPointerSize;
514

    
515
  Major MajorKey() { return NameDictionaryLookup; }
516

    
517
  int MinorKey() {
518
    return LookupModeBits::encode(mode_);
519
  }
520

    
521
  class LookupModeBits: public BitField<LookupMode, 0, 1> {};
522

    
523
  LookupMode mode_;
524
};
525

    
526

    
527
} }  // namespace v8::internal
528

    
529
#endif  // V8_MIPS_CODE_STUBS_ARM_H_