Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(260)

Side by Side Diff: src/a64/code-stubs-a64.h

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/a64/builtins-a64.cc ('k') | src/a64/code-stubs-a64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2013 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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
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 #ifndef V8_ARM_CODE_STUBS_ARM_H_ 28 #ifndef V8_A64_CODE_STUBS_A64_H_
29 #define V8_ARM_CODE_STUBS_ARM_H_ 29 #define V8_A64_CODE_STUBS_A64_H_
30 30
31 #include "ic-inl.h" 31 #include "ic-inl.h"
32 32
33 namespace v8 { 33 namespace v8 {
34 namespace internal { 34 namespace internal {
35 35
36 36
37 void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code); 37 void ArrayNativeCode(MacroAssembler* masm, Label* call_generic_code);
38 38
39 39
40 class StoreBufferOverflowStub: public PlatformCodeStub { 40 class StoreBufferOverflowStub: public PlatformCodeStub {
41 public: 41 public:
42 explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp) 42 explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp)
43 : save_doubles_(save_fp) {} 43 : save_doubles_(save_fp) { }
44 44
45 void Generate(MacroAssembler* masm); 45 void Generate(MacroAssembler* masm);
46 46
47 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate); 47 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
48 virtual bool SometimesSetsUpAFrame() { return false; } 48 virtual bool SometimesSetsUpAFrame() { return false; }
49 49
50 private: 50 private:
51 SaveFPRegsMode save_doubles_; 51 SaveFPRegsMode save_doubles_;
52 52
53 Major MajorKey() { return StoreBufferOverflow; } 53 Major MajorKey() { return StoreBufferOverflow; }
54 int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; } 54 int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; }
55 }; 55 };
56 56
57 57
58 class StringHelper : public AllStatic { 58 class StringHelper : public AllStatic {
59 public: 59 public:
60 // Generate code for copying characters using a simple loop. This should only 60 // TODO(all): These don't seem to be used any more. Delete them.
61 // be used in places where the number of characters is small and the
62 // additional setup and checking in GenerateCopyCharactersLong adds too much
63 // overhead. Copying of overlapping regions is not supported.
64 // Dest register ends at the position after the last character written.
65 static void GenerateCopyCharacters(MacroAssembler* masm,
66 Register dest,
67 Register src,
68 Register count,
69 Register scratch,
70 bool ascii);
71
72 // Generate code for copying a large number of characters. This function
73 // is allowed to spend extra time setting up conditions to make copying
74 // faster. Copying of overlapping regions is not supported.
75 // Dest register ends at the position after the last character written.
76 static void GenerateCopyCharactersLong(MacroAssembler* masm,
77 Register dest,
78 Register src,
79 Register count,
80 Register scratch1,
81 Register scratch2,
82 Register scratch3,
83 Register scratch4,
84 int flags);
85
86
87 // Probe the string table for a two character string. If the string is
88 // not found by probing a jump to the label not_found is performed. This jump
89 // does not guarantee that the string is not in the string table. If the
90 // string is found the code falls through with the string in register r0.
91 // Contents of both c1 and c2 registers are modified. At the exit c1 is
92 // guaranteed to contain halfword with low and high bytes equal to
93 // initial contents of c1 and c2 respectively.
94 static void GenerateTwoCharacterStringTableProbe(MacroAssembler* masm,
95 Register c1,
96 Register c2,
97 Register scratch1,
98 Register scratch2,
99 Register scratch3,
100 Register scratch4,
101 Register scratch5,
102 Label* not_found);
103 61
104 // Generate string hash. 62 // Generate string hash.
105 static void GenerateHashInit(MacroAssembler* masm, 63 static void GenerateHashInit(MacroAssembler* masm,
106 Register hash, 64 Register hash,
107 Register character); 65 Register character);
108 66
109 static void GenerateHashAddCharacter(MacroAssembler* masm, 67 static void GenerateHashAddCharacter(MacroAssembler* masm,
110 Register hash, 68 Register hash,
111 Register character); 69 Register character);
112 70
113 static void GenerateHashGetHash(MacroAssembler* masm, 71 static void GenerateHashGetHash(MacroAssembler* masm,
114 Register hash); 72 Register hash,
73 Register scratch);
115 74
116 private: 75 private:
117 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper); 76 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
118 }; 77 };
119 78
120 79
121 class StringAddStub: public PlatformCodeStub {
122 public:
123 explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
124
125 private:
126 Major MajorKey() { return StringAdd; }
127 int MinorKey() { return flags_; }
128
129 void Generate(MacroAssembler* masm);
130
131 void GenerateConvertArgument(MacroAssembler* masm,
132 int stack_offset,
133 Register arg,
134 Register scratch1,
135 Register scratch2,
136 Register scratch3,
137 Register scratch4,
138 Label* slow);
139
140 void GenerateRegisterArgsPush(MacroAssembler* masm);
141 void GenerateRegisterArgsPop(MacroAssembler* masm);
142
143 const StringAddFlags flags_;
144 };
145
146
147 class SubStringStub: public PlatformCodeStub {
148 public:
149 SubStringStub() {}
150
151 private:
152 Major MajorKey() { return SubString; }
153 int MinorKey() { return 0; }
154
155 void Generate(MacroAssembler* masm);
156 };
157
158
159
160 class StringCompareStub: public PlatformCodeStub {
161 public:
162 StringCompareStub() { }
163
164 // Compares two flat ASCII strings and returns result in r0.
165 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
166 Register left,
167 Register right,
168 Register scratch1,
169 Register scratch2,
170 Register scratch3,
171 Register scratch4);
172
173 // Compares two flat ASCII strings for equality and returns result
174 // in r0.
175 static void GenerateFlatAsciiStringEquals(MacroAssembler* masm,
176 Register left,
177 Register right,
178 Register scratch1,
179 Register scratch2,
180 Register scratch3);
181
182 private:
183 virtual Major MajorKey() { return StringCompare; }
184 virtual int MinorKey() { return 0; }
185 virtual void Generate(MacroAssembler* masm);
186
187 static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm,
188 Register left,
189 Register right,
190 Register length,
191 Register scratch1,
192 Register scratch2,
193 Label* chars_not_equal);
194 };
195
196
197 // This stub can convert a signed int32 to a heap number (double). It does
198 // not work for int32s that are in Smi range! No GC occurs during this stub
199 // so you don't have to set up the frame.
200 class WriteInt32ToHeapNumberStub : public PlatformCodeStub {
201 public:
202 WriteInt32ToHeapNumberStub(Register the_int,
203 Register the_heap_number,
204 Register scratch)
205 : the_int_(the_int),
206 the_heap_number_(the_heap_number),
207 scratch_(scratch) { }
208
209 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
210
211 private:
212 Register the_int_;
213 Register the_heap_number_;
214 Register scratch_;
215
216 // Minor key encoding in 16 bits.
217 class IntRegisterBits: public BitField<int, 0, 4> {};
218 class HeapNumberRegisterBits: public BitField<int, 4, 4> {};
219 class ScratchRegisterBits: public BitField<int, 8, 4> {};
220
221 Major MajorKey() { return WriteInt32ToHeapNumber; }
222 int MinorKey() {
223 // Encode the parameters in a unique 16 bit value.
224 return IntRegisterBits::encode(the_int_.code())
225 | HeapNumberRegisterBits::encode(the_heap_number_.code())
226 | ScratchRegisterBits::encode(scratch_.code());
227 }
228
229 void Generate(MacroAssembler* masm);
230 };
231
232
233 class RecordWriteStub: public PlatformCodeStub { 80 class RecordWriteStub: public PlatformCodeStub {
234 public: 81 public:
82 // Stub to record the write of 'value' at 'address' in 'object'.
83 // Typically 'address' = 'object' + <some offset>.
84 // See MacroAssembler::RecordWriteField() for example.
235 RecordWriteStub(Register object, 85 RecordWriteStub(Register object,
236 Register value, 86 Register value,
237 Register address, 87 Register address,
238 RememberedSetAction remembered_set_action, 88 RememberedSetAction remembered_set_action,
239 SaveFPRegsMode fp_mode) 89 SaveFPRegsMode fp_mode)
240 : object_(object), 90 : object_(object),
241 value_(value), 91 value_(value),
242 address_(address), 92 address_(address),
243 remembered_set_action_(remembered_set_action), 93 remembered_set_action_(remembered_set_action),
244 save_fp_regs_mode_(fp_mode), 94 save_fp_regs_mode_(fp_mode),
245 regs_(object, // An input reg. 95 regs_(object, // An input reg.
246 address, // An input reg. 96 address, // An input reg.
247 value) { // One scratch reg. 97 value) { // One scratch reg.
248 } 98 }
249 99
250 enum Mode { 100 enum Mode {
251 STORE_BUFFER_ONLY, 101 STORE_BUFFER_ONLY,
252 INCREMENTAL, 102 INCREMENTAL,
253 INCREMENTAL_COMPACTION 103 INCREMENTAL_COMPACTION
254 }; 104 };
255 105
256 virtual bool SometimesSetsUpAFrame() { return false; } 106 virtual bool SometimesSetsUpAFrame() { return false; }
257 107
258 static void PatchBranchIntoNop(MacroAssembler* masm, int pos) { 108 static Mode GetMode(Code* stub) {
259 masm->instr_at_put(pos, (masm->instr_at(pos) & ~B27) | (B24 | B20)); 109 // Find the mode depending on the first two instructions.
260 ASSERT(Assembler::IsTstImmediate(masm->instr_at(pos))); 110 Instruction* instr1 =
261 } 111 reinterpret_cast<Instruction*>(stub->instruction_start());
112 Instruction* instr2 = instr1->following();
262 113
263 static void PatchNopIntoBranch(MacroAssembler* masm, int pos) { 114 if (instr1->IsUncondBranchImm()) {
264 masm->instr_at_put(pos, (masm->instr_at(pos) & ~(B24 | B20)) | B27); 115 ASSERT(instr2->IsPCRelAddressing() && (instr2->Rd() == xzr.code()));
265 ASSERT(Assembler::IsBranch(masm->instr_at(pos)));
266 }
267
268 static Mode GetMode(Code* stub) {
269 Instr first_instruction = Assembler::instr_at(stub->instruction_start());
270 Instr second_instruction = Assembler::instr_at(stub->instruction_start() +
271 Assembler::kInstrSize);
272
273 if (Assembler::IsBranch(first_instruction)) {
274 return INCREMENTAL; 116 return INCREMENTAL;
275 } 117 }
276 118
277 ASSERT(Assembler::IsTstImmediate(first_instruction)); 119 ASSERT(instr1->IsPCRelAddressing() && (instr1->Rd() == xzr.code()));
278 120
279 if (Assembler::IsBranch(second_instruction)) { 121 if (instr2->IsUncondBranchImm()) {
280 return INCREMENTAL_COMPACTION; 122 return INCREMENTAL_COMPACTION;
281 } 123 }
282 124
283 ASSERT(Assembler::IsTstImmediate(second_instruction)); 125 ASSERT(instr2->IsPCRelAddressing());
284 126
285 return STORE_BUFFER_ONLY; 127 return STORE_BUFFER_ONLY;
286 } 128 }
287 129
130 // We patch the two first instructions of the stub back and forth between an
131 // adr and branch when we start and stop incremental heap marking.
132 // The branch is
133 // b label
134 // The adr is
135 // adr xzr label
136 // so effectively a nop.
288 static void Patch(Code* stub, Mode mode) { 137 static void Patch(Code* stub, Mode mode) {
289 MacroAssembler masm(NULL, 138 // We are going to patch the two first instructions of the stub.
290 stub->instruction_start(), 139 PatchingAssembler patcher(
291 stub->instruction_size()); 140 reinterpret_cast<Instruction*>(stub->instruction_start()), 2);
141 Instruction* instr1 = patcher.InstructionAt(0);
142 Instruction* instr2 = patcher.InstructionAt(kInstructionSize);
143 // Instructions must be either 'adr' or 'b'.
144 ASSERT(instr1->IsPCRelAddressing() || instr1->IsUncondBranchImm());
145 ASSERT(instr2->IsPCRelAddressing() || instr2->IsUncondBranchImm());
146 // Retrieve the offsets to the labels.
147 int32_t offset_to_incremental_noncompacting = instr1->ImmPCOffset();
148 int32_t offset_to_incremental_compacting = instr2->ImmPCOffset();
149
292 switch (mode) { 150 switch (mode) {
293 case STORE_BUFFER_ONLY: 151 case STORE_BUFFER_ONLY:
294 ASSERT(GetMode(stub) == INCREMENTAL || 152 ASSERT(GetMode(stub) == INCREMENTAL ||
295 GetMode(stub) == INCREMENTAL_COMPACTION); 153 GetMode(stub) == INCREMENTAL_COMPACTION);
296 PatchBranchIntoNop(&masm, 0); 154 patcher.adr(xzr, offset_to_incremental_noncompacting);
297 PatchBranchIntoNop(&masm, Assembler::kInstrSize); 155 patcher.adr(xzr, offset_to_incremental_compacting);
298 break; 156 break;
299 case INCREMENTAL: 157 case INCREMENTAL:
300 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY); 158 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
301 PatchNopIntoBranch(&masm, 0); 159 patcher.b(offset_to_incremental_noncompacting >> kInstructionSizeLog2);
160 patcher.adr(xzr, offset_to_incremental_compacting);
302 break; 161 break;
303 case INCREMENTAL_COMPACTION: 162 case INCREMENTAL_COMPACTION:
304 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY); 163 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
305 PatchNopIntoBranch(&masm, Assembler::kInstrSize); 164 patcher.adr(xzr, offset_to_incremental_noncompacting);
165 patcher.b(offset_to_incremental_compacting >> kInstructionSizeLog2);
306 break; 166 break;
307 } 167 }
308 ASSERT(GetMode(stub) == mode); 168 ASSERT(GetMode(stub) == mode);
309 CPU::FlushICache(stub->instruction_start(), 2 * Assembler::kInstrSize);
310 } 169 }
311 170
312 private: 171 private:
313 // This is a helper class for freeing up 3 scratch registers. The input is 172 // This is a helper class to manage the registers associated with the stub.
314 // two registers that must be preserved and one scratch register provided by 173 // The 'object' and 'address' registers must be preserved.
315 // the caller.
316 class RegisterAllocation { 174 class RegisterAllocation {
317 public: 175 public:
318 RegisterAllocation(Register object, 176 RegisterAllocation(Register object,
319 Register address, 177 Register address,
320 Register scratch0) 178 Register scratch)
321 : object_(object), 179 : object_(object),
322 address_(address), 180 address_(address),
323 scratch0_(scratch0) { 181 scratch0_(scratch),
324 ASSERT(!AreAliased(scratch0, object, address, no_reg)); 182 saved_regs_(kCallerSaved) {
325 scratch1_ = GetRegisterThatIsNotOneOf(object_, address_, scratch0_); 183 ASSERT(!AreAliased(scratch, object, address));
184
185 // We would like to require more scratch registers for this stub,
186 // but the number of registers comes down to the ones used in
187 // FullCodeGen::SetVar(), which is architecture independent.
188 // We allocate 2 extra scratch registers that we'll save on the stack.
189 CPURegList pool_available = GetValidRegistersForAllocation();
190 CPURegList used_regs(object, address, scratch);
191 pool_available.Remove(used_regs);
192 scratch1_ = Register(pool_available.PopLowestIndex());
193 scratch2_ = Register(pool_available.PopLowestIndex());
194
195 // SaveCallerRegisters method needs to save caller saved register, however
196 // we don't bother saving ip0 and ip1 because they are used as scratch
197 // registers by the MacroAssembler.
198 saved_regs_.Remove(ip0);
199 saved_regs_.Remove(ip1);
200
201 // The scratch registers will be restored by other means so we don't need
202 // to save them with the other caller saved registers.
203 saved_regs_.Remove(scratch0_);
204 saved_regs_.Remove(scratch1_);
205 saved_regs_.Remove(scratch2_);
326 } 206 }
327 207
328 void Save(MacroAssembler* masm) { 208 void Save(MacroAssembler* masm) {
329 ASSERT(!AreAliased(object_, address_, scratch1_, scratch0_));
330 // We don't have to save scratch0_ because it was given to us as 209 // We don't have to save scratch0_ because it was given to us as
331 // a scratch register. 210 // a scratch register.
332 masm->push(scratch1_); 211 masm->Push(scratch1_, scratch2_);
333 } 212 }
334 213
335 void Restore(MacroAssembler* masm) { 214 void Restore(MacroAssembler* masm) {
336 masm->pop(scratch1_); 215 masm->Pop(scratch2_, scratch1_);
337 } 216 }
338 217
339 // If we have to call into C then we need to save and restore all caller- 218 // If we have to call into C then we need to save and restore all caller-
340 // saved registers that were not already preserved. The scratch registers 219 // saved registers that were not already preserved.
341 // will be restored by other means so we don't bother pushing them here.
342 void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) { 220 void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
343 masm->stm(db_w, sp, (kCallerSaved | lr.bit()) & ~scratch1_.bit()); 221 // TODO(all): This can be very expensive, and it is likely that not every
222 // register will need to be preserved. Can we improve this?
223 masm->PushCPURegList(saved_regs_);
344 if (mode == kSaveFPRegs) { 224 if (mode == kSaveFPRegs) {
345 masm->SaveFPRegs(sp, scratch0_); 225 masm->PushCPURegList(kCallerSavedFP);
346 } 226 }
347 } 227 }
348 228
349 inline void RestoreCallerSaveRegisters(MacroAssembler*masm, 229 void RestoreCallerSaveRegisters(MacroAssembler*masm, SaveFPRegsMode mode) {
350 SaveFPRegsMode mode) { 230 // TODO(all): This can be very expensive, and it is likely that not every
231 // register will need to be preserved. Can we improve this?
351 if (mode == kSaveFPRegs) { 232 if (mode == kSaveFPRegs) {
352 masm->RestoreFPRegs(sp, scratch0_); 233 masm->PopCPURegList(kCallerSavedFP);
353 } 234 }
354 masm->ldm(ia_w, sp, (kCallerSaved | lr.bit()) & ~scratch1_.bit()); 235 masm->PopCPURegList(saved_regs_);
355 } 236 }
356 237
357 inline Register object() { return object_; } 238 Register object() { return object_; }
358 inline Register address() { return address_; } 239 Register address() { return address_; }
359 inline Register scratch0() { return scratch0_; } 240 Register scratch0() { return scratch0_; }
360 inline Register scratch1() { return scratch1_; } 241 Register scratch1() { return scratch1_; }
242 Register scratch2() { return scratch2_; }
361 243
362 private: 244 private:
363 Register object_; 245 Register object_;
364 Register address_; 246 Register address_;
365 Register scratch0_; 247 Register scratch0_;
366 Register scratch1_; 248 Register scratch1_;
249 Register scratch2_;
250 CPURegList saved_regs_;
251
252 // TODO(all): We should consider moving this somewhere else.
253 static CPURegList GetValidRegistersForAllocation() {
254 // The list of valid registers for allocation is defined as all the
255 // registers without those with a special meaning.
256 //
257 // The default list excludes registers x26 to x31 because they are
258 // reserved for the following purpose:
259 // - x26 root register
260 // - x27 context pointer register
261 // - x28 jssp
262 // - x29 frame pointer
263 // - x30 link register(lr)
264 // - x31 xzr/stack pointer
265 CPURegList list(CPURegister::kRegister, kXRegSize, 0, 25);
266
267 // We also remove MacroAssembler's scratch registers.
268 list.Remove(ip0);
269 list.Remove(ip1);
270 list.Remove(x8);
271 list.Remove(x9);
272
273 return list;
274 }
367 275
368 friend class RecordWriteStub; 276 friend class RecordWriteStub;
369 }; 277 };
370 278
279 // A list of stub variants which are pregenerated.
280 // The variants are stored in the same format as the minor key, so
281 // MinorKeyFor() can be used to populate and check this list.
282 static const int kAheadOfTime[];
283
284 void Generate(MacroAssembler* masm);
285 void GenerateIncremental(MacroAssembler* masm, Mode mode);
286
371 enum OnNoNeedToInformIncrementalMarker { 287 enum OnNoNeedToInformIncrementalMarker {
372 kReturnOnNoNeedToInformIncrementalMarker, 288 kReturnOnNoNeedToInformIncrementalMarker,
373 kUpdateRememberedSetOnNoNeedToInformIncrementalMarker 289 kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
374 }; 290 };
375 291
376 void Generate(MacroAssembler* masm);
377 void GenerateIncremental(MacroAssembler* masm, Mode mode);
378 void CheckNeedsToInformIncrementalMarker( 292 void CheckNeedsToInformIncrementalMarker(
379 MacroAssembler* masm, 293 MacroAssembler* masm,
380 OnNoNeedToInformIncrementalMarker on_no_need, 294 OnNoNeedToInformIncrementalMarker on_no_need,
381 Mode mode); 295 Mode mode);
382 void InformIncrementalMarker(MacroAssembler* masm, Mode mode); 296 void InformIncrementalMarker(MacroAssembler* masm, Mode mode);
383 297
384 Major MajorKey() { return RecordWrite; } 298 Major MajorKey() { return RecordWrite; }
385 299
386 int MinorKey() { 300 int MinorKey() {
387 return ObjectBits::encode(object_.code()) | 301 return MinorKeyFor(object_, value_, address_, remembered_set_action_,
388 ValueBits::encode(value_.code()) | 302 save_fp_regs_mode_);
389 AddressBits::encode(address_.code()) | 303 }
390 RememberedSetActionBits::encode(remembered_set_action_) | 304
391 SaveFPRegsModeBits::encode(save_fp_regs_mode_); 305 static int MinorKeyFor(Register object,
306 Register value,
307 Register address,
308 RememberedSetAction action,
309 SaveFPRegsMode fp_mode) {
310 ASSERT(object.Is64Bits());
311 ASSERT(value.Is64Bits());
312 ASSERT(address.Is64Bits());
313 return ObjectBits::encode(object.code()) |
314 ValueBits::encode(value.code()) |
315 AddressBits::encode(address.code()) |
316 RememberedSetActionBits::encode(action) |
317 SaveFPRegsModeBits::encode(fp_mode);
392 } 318 }
393 319
394 void Activate(Code* code) { 320 void Activate(Code* code) {
395 code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code); 321 code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
396 } 322 }
397 323
398 class ObjectBits: public BitField<int, 0, 4> {}; 324 class ObjectBits: public BitField<int, 0, 5> {};
399 class ValueBits: public BitField<int, 4, 4> {}; 325 class ValueBits: public BitField<int, 5, 5> {};
400 class AddressBits: public BitField<int, 8, 4> {}; 326 class AddressBits: public BitField<int, 10, 5> {};
401 class RememberedSetActionBits: public BitField<RememberedSetAction, 12, 1> {}; 327 class RememberedSetActionBits: public BitField<RememberedSetAction, 15, 1> {};
402 class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 13, 1> {}; 328 class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 16, 1> {};
403 329
404 Register object_; 330 Register object_;
405 Register value_; 331 Register value_;
406 Register address_; 332 Register address_;
407 RememberedSetAction remembered_set_action_; 333 RememberedSetAction remembered_set_action_;
408 SaveFPRegsMode save_fp_regs_mode_; 334 SaveFPRegsMode save_fp_regs_mode_;
409 Label slow_; 335 Label slow_;
410 RegisterAllocation regs_; 336 RegisterAllocation regs_;
411 }; 337 };
412 338
413 339
414 // Trampoline stub to call into native code. To call safely into native code 340 // Helper to call C++ functions from generated code. The caller must prepare
415 // in the presence of compacting GC (which can move code objects) we need to 341 // the exit frame before doing the call with GenerateCall.
416 // keep the code which called into native pinned in the memory. Currently the
417 // simplest approach is to generate such stub early enough so it can never be
418 // moved by GC
419 class DirectCEntryStub: public PlatformCodeStub { 342 class DirectCEntryStub: public PlatformCodeStub {
420 public: 343 public:
421 DirectCEntryStub() {} 344 DirectCEntryStub() {}
422 void Generate(MacroAssembler* masm); 345 void Generate(MacroAssembler* masm);
423 void GenerateCall(MacroAssembler* masm, Register target); 346 void GenerateCall(MacroAssembler* masm, Register target);
424 347
425 private: 348 private:
426 Major MajorKey() { return DirectCEntry; } 349 Major MajorKey() { return DirectCEntry; }
427 int MinorKey() { return 0; } 350 int MinorKey() { return 0; }
428 351
(...skipping 15 matching lines...) Expand all
444 Register receiver, 367 Register receiver,
445 Register properties, 368 Register properties,
446 Handle<Name> name, 369 Handle<Name> name,
447 Register scratch0); 370 Register scratch0);
448 371
449 static void GeneratePositiveLookup(MacroAssembler* masm, 372 static void GeneratePositiveLookup(MacroAssembler* masm,
450 Label* miss, 373 Label* miss,
451 Label* done, 374 Label* done,
452 Register elements, 375 Register elements,
453 Register name, 376 Register name,
454 Register r0, 377 Register scratch1,
455 Register r1); 378 Register scratch2);
456 379
457 virtual bool SometimesSetsUpAFrame() { return false; } 380 virtual bool SometimesSetsUpAFrame() { return false; }
458 381
459 private: 382 private:
460 static const int kInlinedProbes = 4; 383 static const int kInlinedProbes = 4;
461 static const int kTotalProbes = 20; 384 static const int kTotalProbes = 20;
462 385
463 static const int kCapacityOffset = 386 static const int kCapacityOffset =
464 NameDictionary::kHeaderSize + 387 NameDictionary::kHeaderSize +
465 NameDictionary::kCapacityIndex * kPointerSize; 388 NameDictionary::kCapacityIndex * kPointerSize;
466 389
467 static const int kElementsStartOffset = 390 static const int kElementsStartOffset =
468 NameDictionary::kHeaderSize + 391 NameDictionary::kHeaderSize +
469 NameDictionary::kElementsStartIndex * kPointerSize; 392 NameDictionary::kElementsStartIndex * kPointerSize;
470 393
471 Major MajorKey() { return NameDictionaryLookup; } 394 Major MajorKey() { return NameDictionaryLookup; }
472 395
473 int MinorKey() { 396 int MinorKey() {
474 return LookupModeBits::encode(mode_); 397 return LookupModeBits::encode(mode_);
475 } 398 }
476 399
477 class LookupModeBits: public BitField<LookupMode, 0, 1> {}; 400 class LookupModeBits: public BitField<LookupMode, 0, 1> {};
478 401
479 LookupMode mode_; 402 LookupMode mode_;
480 }; 403 };
481 404
482 405
406 class SubStringStub: public PlatformCodeStub {
407 public:
408 SubStringStub() {}
409
410 private:
411 Major MajorKey() { return SubString; }
412 int MinorKey() { return 0; }
413
414 void Generate(MacroAssembler* masm);
415 };
416
417
418 class StringCompareStub: public PlatformCodeStub {
419 public:
420 StringCompareStub() { }
421
422 // Compares two flat ASCII strings and returns result in x0.
423 static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
424 Register left,
425 Register right,
426 Register scratch1,
427 Register scratch2,
428 Register scratch3,
429 Register scratch4);
430
431 // Compare two flat ASCII strings for equality and returns result
432 // in x0.
433 static void GenerateFlatAsciiStringEquals(MacroAssembler* masm,
434 Register left,
435 Register right,
436 Register scratch1,
437 Register scratch2,
438 Register scratch3);
439
440 private:
441 virtual Major MajorKey() { return StringCompare; }
442 virtual int MinorKey() { return 0; }
443 virtual void Generate(MacroAssembler* masm);
444
445 static void GenerateAsciiCharsCompareLoop(MacroAssembler* masm,
446 Register left,
447 Register right,
448 Register length,
449 Register scratch1,
450 Register scratch2,
451 Label* chars_not_equal);
452 };
453
454
483 struct PlatformCallInterfaceDescriptor { 455 struct PlatformCallInterfaceDescriptor {
484 explicit PlatformCallInterfaceDescriptor( 456 explicit PlatformCallInterfaceDescriptor(
485 TargetAddressStorageMode storage_mode) 457 TargetAddressStorageMode storage_mode)
486 : storage_mode_(storage_mode) { } 458 : storage_mode_(storage_mode) { }
487 459
488 TargetAddressStorageMode storage_mode() { return storage_mode_; } 460 TargetAddressStorageMode storage_mode() { return storage_mode_; }
489 461
490 private: 462 private:
491 TargetAddressStorageMode storage_mode_; 463 TargetAddressStorageMode storage_mode_;
492 }; 464 };
493 465
494 466
495 } } // namespace v8::internal 467 } } // namespace v8::internal
496 468
497 #endif // V8_ARM_CODE_STUBS_ARM_H_ 469 #endif // V8_A64_CODE_STUBS_A64_H_
OLDNEW
« no previous file with comments | « src/a64/builtins-a64.cc ('k') | src/a64/code-stubs-a64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698