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

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

Issue 207823003: Rename A64 port to ARM64 port (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: retry 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
(Empty)
1 // Copyright 2013 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_A64_CODE_STUBS_A64_H_
29 #define V8_A64_CODE_STUBS_A64_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 class StoreBufferOverflowStub: public PlatformCodeStub {
41 public:
42 explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp)
43 : save_doubles_(save_fp) { }
44
45 void Generate(MacroAssembler* masm);
46
47 static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
48 virtual bool SometimesSetsUpAFrame() { return false; }
49
50 private:
51 SaveFPRegsMode save_doubles_;
52
53 Major MajorKey() { return StoreBufferOverflow; }
54 int MinorKey() { return (save_doubles_ == kSaveFPRegs) ? 1 : 0; }
55 };
56
57
58 class StringHelper : public AllStatic {
59 public:
60 // TODO(all): These don't seem to be used any more. Delete them.
61
62 // Generate string hash.
63 static void GenerateHashInit(MacroAssembler* masm,
64 Register hash,
65 Register character);
66
67 static void GenerateHashAddCharacter(MacroAssembler* masm,
68 Register hash,
69 Register character);
70
71 static void GenerateHashGetHash(MacroAssembler* masm,
72 Register hash,
73 Register scratch);
74
75 private:
76 DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
77 };
78
79
80 class RecordWriteStub: public PlatformCodeStub {
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.
85 RecordWriteStub(Register object,
86 Register value,
87 Register address,
88 RememberedSetAction remembered_set_action,
89 SaveFPRegsMode fp_mode)
90 : object_(object),
91 value_(value),
92 address_(address),
93 remembered_set_action_(remembered_set_action),
94 save_fp_regs_mode_(fp_mode),
95 regs_(object, // An input reg.
96 address, // An input reg.
97 value) { // One scratch reg.
98 }
99
100 enum Mode {
101 STORE_BUFFER_ONLY,
102 INCREMENTAL,
103 INCREMENTAL_COMPACTION
104 };
105
106 virtual bool SometimesSetsUpAFrame() { return false; }
107
108 static Mode GetMode(Code* stub) {
109 // Find the mode depending on the first two instructions.
110 Instruction* instr1 =
111 reinterpret_cast<Instruction*>(stub->instruction_start());
112 Instruction* instr2 = instr1->following();
113
114 if (instr1->IsUncondBranchImm()) {
115 ASSERT(instr2->IsPCRelAddressing() && (instr2->Rd() == xzr.code()));
116 return INCREMENTAL;
117 }
118
119 ASSERT(instr1->IsPCRelAddressing() && (instr1->Rd() == xzr.code()));
120
121 if (instr2->IsUncondBranchImm()) {
122 return INCREMENTAL_COMPACTION;
123 }
124
125 ASSERT(instr2->IsPCRelAddressing());
126
127 return STORE_BUFFER_ONLY;
128 }
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.
137 static void Patch(Code* stub, Mode mode) {
138 // We are going to patch the two first instructions of the stub.
139 PatchingAssembler patcher(
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
150 switch (mode) {
151 case STORE_BUFFER_ONLY:
152 ASSERT(GetMode(stub) == INCREMENTAL ||
153 GetMode(stub) == INCREMENTAL_COMPACTION);
154 patcher.adr(xzr, offset_to_incremental_noncompacting);
155 patcher.adr(xzr, offset_to_incremental_compacting);
156 break;
157 case INCREMENTAL:
158 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
159 patcher.b(offset_to_incremental_noncompacting >> kInstructionSizeLog2);
160 patcher.adr(xzr, offset_to_incremental_compacting);
161 break;
162 case INCREMENTAL_COMPACTION:
163 ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
164 patcher.adr(xzr, offset_to_incremental_noncompacting);
165 patcher.b(offset_to_incremental_compacting >> kInstructionSizeLog2);
166 break;
167 }
168 ASSERT(GetMode(stub) == mode);
169 }
170
171 private:
172 // This is a helper class to manage the registers associated with the stub.
173 // The 'object' and 'address' registers must be preserved.
174 class RegisterAllocation {
175 public:
176 RegisterAllocation(Register object,
177 Register address,
178 Register scratch)
179 : object_(object),
180 address_(address),
181 scratch0_(scratch),
182 saved_regs_(kCallerSaved) {
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_);
206 }
207
208 void Save(MacroAssembler* masm) {
209 // We don't have to save scratch0_ because it was given to us as
210 // a scratch register.
211 masm->Push(scratch1_, scratch2_);
212 }
213
214 void Restore(MacroAssembler* masm) {
215 masm->Pop(scratch2_, scratch1_);
216 }
217
218 // If we have to call into C then we need to save and restore all caller-
219 // saved registers that were not already preserved.
220 void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
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_);
224 if (mode == kSaveFPRegs) {
225 masm->PushCPURegList(kCallerSavedFP);
226 }
227 }
228
229 void RestoreCallerSaveRegisters(MacroAssembler*masm, 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?
232 if (mode == kSaveFPRegs) {
233 masm->PopCPURegList(kCallerSavedFP);
234 }
235 masm->PopCPURegList(saved_regs_);
236 }
237
238 Register object() { return object_; }
239 Register address() { return address_; }
240 Register scratch0() { return scratch0_; }
241 Register scratch1() { return scratch1_; }
242 Register scratch2() { return scratch2_; }
243
244 private:
245 Register object_;
246 Register address_;
247 Register scratch0_;
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, kXRegSizeInBits, 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 }
275
276 friend class RecordWriteStub;
277 };
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
287 enum OnNoNeedToInformIncrementalMarker {
288 kReturnOnNoNeedToInformIncrementalMarker,
289 kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
290 };
291
292 void CheckNeedsToInformIncrementalMarker(
293 MacroAssembler* masm,
294 OnNoNeedToInformIncrementalMarker on_no_need,
295 Mode mode);
296 void InformIncrementalMarker(MacroAssembler* masm);
297
298 Major MajorKey() { return RecordWrite; }
299
300 int MinorKey() {
301 return MinorKeyFor(object_, value_, address_, remembered_set_action_,
302 save_fp_regs_mode_);
303 }
304
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);
318 }
319
320 void Activate(Code* code) {
321 code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
322 }
323
324 class ObjectBits: public BitField<int, 0, 5> {};
325 class ValueBits: public BitField<int, 5, 5> {};
326 class AddressBits: public BitField<int, 10, 5> {};
327 class RememberedSetActionBits: public BitField<RememberedSetAction, 15, 1> {};
328 class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 16, 1> {};
329
330 Register object_;
331 Register value_;
332 Register address_;
333 RememberedSetAction remembered_set_action_;
334 SaveFPRegsMode save_fp_regs_mode_;
335 Label slow_;
336 RegisterAllocation regs_;
337 };
338
339
340 // Helper to call C++ functions from generated code. The caller must prepare
341 // the exit frame before doing the call with GenerateCall.
342 class DirectCEntryStub: public PlatformCodeStub {
343 public:
344 DirectCEntryStub() {}
345 void Generate(MacroAssembler* masm);
346 void GenerateCall(MacroAssembler* masm, Register target);
347
348 private:
349 Major MajorKey() { return DirectCEntry; }
350 int MinorKey() { return 0; }
351
352 bool NeedsImmovableCode() { return true; }
353 };
354
355
356 class NameDictionaryLookupStub: public PlatformCodeStub {
357 public:
358 enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
359
360 explicit NameDictionaryLookupStub(LookupMode mode) : mode_(mode) { }
361
362 void Generate(MacroAssembler* masm);
363
364 static void GenerateNegativeLookup(MacroAssembler* masm,
365 Label* miss,
366 Label* done,
367 Register receiver,
368 Register properties,
369 Handle<Name> name,
370 Register scratch0);
371
372 static void GeneratePositiveLookup(MacroAssembler* masm,
373 Label* miss,
374 Label* done,
375 Register elements,
376 Register name,
377 Register scratch1,
378 Register scratch2);
379
380 virtual bool SometimesSetsUpAFrame() { return false; }
381
382 private:
383 static const int kInlinedProbes = 4;
384 static const int kTotalProbes = 20;
385
386 static const int kCapacityOffset =
387 NameDictionary::kHeaderSize +
388 NameDictionary::kCapacityIndex * kPointerSize;
389
390 static const int kElementsStartOffset =
391 NameDictionary::kHeaderSize +
392 NameDictionary::kElementsStartIndex * kPointerSize;
393
394 Major MajorKey() { return NameDictionaryLookup; }
395
396 int MinorKey() {
397 return LookupModeBits::encode(mode_);
398 }
399
400 class LookupModeBits: public BitField<LookupMode, 0, 1> {};
401
402 LookupMode mode_;
403 };
404
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
455 struct PlatformCallInterfaceDescriptor {
456 explicit PlatformCallInterfaceDescriptor(
457 TargetAddressStorageMode storage_mode)
458 : storage_mode_(storage_mode) { }
459
460 TargetAddressStorageMode storage_mode() { return storage_mode_; }
461
462 private:
463 TargetAddressStorageMode storage_mode_;
464 };
465
466
467 } } // namespace v8::internal
468
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