V8 Project
code-stubs-x87.h
Go to the documentation of this file.
1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_X87_CODE_STUBS_X87_H_
6 #define V8_X87_CODE_STUBS_X87_H_
7 
8 namespace v8 {
9 namespace internal {
10 
11 
12 void ArrayNativeCode(MacroAssembler* masm,
13  bool construct_call,
14  Label* call_generic_code);
15 
16 
17 class StringHelper : public AllStatic {
18  public:
19  // Generate code for copying characters using the rep movs instruction.
20  // Copies ecx characters from esi to edi. Copying of overlapping regions is
21  // not supported.
23  Register dest,
24  Register src,
25  Register count,
26  Register scratch,
27  String::Encoding encoding);
28 
29  // Compares two flat one byte strings and returns result in eax.
31  Register left, Register right,
32  Register scratch1,
33  Register scratch2,
34  Register scratch3);
35 
36  // Compares two flat one byte strings for equality and returns result in eax.
38  Register left, Register right,
39  Register scratch1,
40  Register scratch2);
41 
42  private:
44  MacroAssembler* masm, Register left, Register right, Register length,
45  Register scratch, Label* chars_not_equal,
46  Label::Distance chars_not_equal_near = Label::kFar);
47 
49 };
50 
51 
53  public:
55 
58  : PlatformCodeStub(isolate) {
59  minor_key_ = DictionaryBits::encode(dictionary.code()) |
62  }
63 
65  Label* miss,
66  Label* done,
67  Register properties,
69  Register r0);
70 
72  Label* miss,
73  Label* done,
74  Register elements,
75  Register name,
76  Register r0,
77  Register r1);
78 
79  virtual bool SometimesSetsUpAFrame() { return false; }
80 
81  private:
82  static const int kInlinedProbes = 4;
83  static const int kTotalProbes = 20;
84 
85  static const int kCapacityOffset =
88 
89  static const int kElementsStartOffset =
92 
93  Register dictionary() const {
94  return Register::from_code(DictionaryBits::decode(minor_key_));
95  }
96 
97  Register result() const {
98  return Register::from_code(ResultBits::decode(minor_key_));
99  }
100 
101  Register index() const {
102  return Register::from_code(IndexBits::decode(minor_key_));
103  }
104 
105  LookupMode mode() const { return LookupModeBits::decode(minor_key_); }
106 
107  class DictionaryBits: public BitField<int, 0, 3> {};
108  class ResultBits: public BitField<int, 3, 3> {};
109  class IndexBits: public BitField<int, 6, 3> {};
110  class LookupModeBits: public BitField<LookupMode, 9, 1> {};
111 
114 };
115 
116 
117 class RecordWriteStub: public PlatformCodeStub {
118  public:
121  SaveFPRegsMode fp_mode)
122  : PlatformCodeStub(isolate),
123  regs_(object, // An input reg.
124  address, // An input reg.
125  value) { // One scratch reg.
126  minor_key_ = ObjectBits::encode(object.code()) |
131  }
132 
134  : PlatformCodeStub(key, isolate), regs_(object(), address(), value()) {}
135 
136  enum Mode {
138  INCREMENTAL,
140  };
141 
142  virtual bool SometimesSetsUpAFrame() { return false; }
143 
144  static const byte kTwoByteNopInstruction = 0x3c; // Cmpb al, #imm8.
145  static const byte kTwoByteJumpInstruction = 0xeb; // Jmp #imm8.
146 
147  static const byte kFiveByteNopInstruction = 0x3d; // Cmpl eax, #imm32.
148  static const byte kFiveByteJumpInstruction = 0xe9; // Jmp #imm32.
149 
150  static Mode GetMode(Code* stub) {
151  byte first_instruction = stub->instruction_start()[0];
152  byte second_instruction = stub->instruction_start()[2];
153 
154  if (first_instruction == kTwoByteJumpInstruction) {
155  return INCREMENTAL;
156  }
157 
158  DCHECK(first_instruction == kTwoByteNopInstruction);
159 
160  if (second_instruction == kFiveByteJumpInstruction) {
161  return INCREMENTAL_COMPACTION;
162  }
163 
164  DCHECK(second_instruction == kFiveByteNopInstruction);
165 
166  return STORE_BUFFER_ONLY;
167  }
168 
169  static void Patch(Code* stub, Mode mode) {
170  switch (mode) {
171  case STORE_BUFFER_ONLY:
172  DCHECK(GetMode(stub) == INCREMENTAL ||
176  break;
177  case INCREMENTAL:
178  DCHECK(GetMode(stub) == STORE_BUFFER_ONLY);
180  break;
182  DCHECK(GetMode(stub) == STORE_BUFFER_ONLY);
185  break;
186  }
187  DCHECK(GetMode(stub) == mode);
189  }
190 
192 
193  private:
194  // This is a helper class for freeing up 3 scratch registers, where the third
195  // is always ecx (needed for shift operations). The input is two registers
196  // that must be preserved and one scratch register provided by the caller.
197  class RegisterAllocation {
198  public:
202  : object_orig_(object),
205  object_(object),
206  address_(address),
208  DCHECK(!AreAliased(scratch0, object, address, no_reg));
210  if (scratch0.is(ecx)) {
212  }
213  if (object.is(ecx)) {
215  }
216  if (address.is(ecx)) {
218  }
220  }
221 
222  void Save(MacroAssembler* masm) {
228  // We don't have to save scratch0_orig_ because it was given to us as
229  // a scratch register. But if we had to switch to a different reg then
230  // we should save the new scratch0_.
231  if (!scratch0_.is(scratch0_orig_)) masm->push(scratch0_);
232  if (!ecx.is(scratch0_orig_) &&
233  !ecx.is(object_orig_) &&
234  !ecx.is(address_orig_)) {
235  masm->push(ecx);
236  }
237  masm->push(scratch1_);
238  if (!address_.is(address_orig_)) {
239  masm->push(address_);
240  masm->mov(address_, address_orig_);
241  }
242  if (!object_.is(object_orig_)) {
243  masm->push(object_);
244  masm->mov(object_, object_orig_);
245  }
246  }
247 
248  void Restore(MacroAssembler* masm) {
249  // These will have been preserved the entire time, so we just need to move
250  // them back. Only in one case is the orig_ reg different from the plain
251  // one, since only one of them can alias with ecx.
252  if (!object_.is(object_orig_)) {
253  masm->mov(object_orig_, object_);
254  masm->pop(object_);
255  }
256  if (!address_.is(address_orig_)) {
257  masm->mov(address_orig_, address_);
258  masm->pop(address_);
259  }
260  masm->pop(scratch1_);
261  if (!ecx.is(scratch0_orig_) &&
262  !ecx.is(object_orig_) &&
263  !ecx.is(address_orig_)) {
264  masm->pop(ecx);
265  }
266  if (!scratch0_.is(scratch0_orig_)) masm->pop(scratch0_);
267  }
268 
269  // If we have to call into C then we need to save and restore all caller-
270  // saved registers that were not already preserved. The caller saved
271  // registers are eax, ecx and edx. The three scratch registers (incl. ecx)
272  // will be restored by other means so we don't bother pushing them here.
274  if (!scratch0_.is(eax) && !scratch1_.is(eax)) masm->push(eax);
275  if (!scratch0_.is(edx) && !scratch1_.is(edx)) masm->push(edx);
276  if (mode == kSaveFPRegs) {
277  // Save FPU state in m108byte.
278  masm->sub(esp, Immediate(108));
279  masm->fnsave(Operand(esp, 0));
280  }
281  }
282 
285  if (mode == kSaveFPRegs) {
286  // Restore FPU state in m108byte.
287  masm->frstor(Operand(esp, 0));
288  masm->add(esp, Immediate(108));
289  }
290  if (!scratch0_.is(edx) && !scratch1_.is(edx)) masm->pop(edx);
291  if (!scratch0_.is(eax) && !scratch1_.is(eax)) masm->pop(eax);
292  }
293 
294  inline Register object() { return object_; }
295  inline Register address() { return address_; }
296  inline Register scratch0() { return scratch0_; }
297  inline Register scratch1() { return scratch1_; }
298 
299  private:
307  // Third scratch register is always ecx.
308 
310  Register r2,
311  Register r3) {
312  for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
314  if (candidate.is(ecx)) continue;
315  if (candidate.is(r1)) continue;
316  if (candidate.is(r2)) continue;
317  if (candidate.is(r3)) continue;
318  return candidate;
319  }
320  UNREACHABLE();
321  return no_reg;
322  }
323  friend class RecordWriteStub;
324  };
325 
329  };
330 
331  virtual inline Major MajorKey() const FINAL OVERRIDE { return RecordWrite; }
332 
333  virtual void Generate(MacroAssembler* masm) OVERRIDE;
336  MacroAssembler* masm,
338  Mode mode);
340 
341  void Activate(Code* code) {
343  }
344 
345  Register object() const {
346  return Register::from_code(ObjectBits::decode(minor_key_));
347  }
348 
349  Register value() const {
350  return Register::from_code(ValueBits::decode(minor_key_));
351  }
352 
353  Register address() const {
354  return Register::from_code(AddressBits::decode(minor_key_));
355  }
356 
358  return RememberedSetActionBits::decode(minor_key_);
359  }
360 
362  return SaveFPRegsModeBits::decode(minor_key_);
363  }
364 
365  class ObjectBits: public BitField<int, 0, 3> {};
366  class ValueBits: public BitField<int, 3, 3> {};
367  class AddressBits: public BitField<int, 6, 3> {};
368  class RememberedSetActionBits: public BitField<RememberedSetAction, 9, 1> {};
369  class SaveFPRegsModeBits : public BitField<SaveFPRegsMode, 10, 1> {};
370 
371  RegisterAllocation regs_;
372 
374 };
375 
376 
377 } } // namespace v8::internal
378 
379 #endif // V8_X87_CODE_STUBS_X87_H_
void fnsave(const Operand &adr)
void add(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void sub(Register dst, Register src1, const Operand &src2, SBit s=LeaveCC, Condition cond=al)
void frstor(const Operand &adr)
static U encode(T value)
Definition: utils.h:217
static T decode(U value)
Definition: utils.h:228
byte * instruction_start()
Definition: objects-inl.h:6176
static void FlushICache(void *start, size_t size)
Source to read snapshot and builtins files from.
Definition: lithium-arm.h:372
static const int kHeaderSize
Definition: objects.h:2393
static const int kElementsStartIndex
Definition: objects.h:3274
static const int kCapacityIndex
Definition: objects.h:3272
Heap * GetHeap() const
Definition: objects-inl.h:1379
IncrementalMarking * incremental_marking()
Definition: heap.h:1205
void mov(Register rd, Register rt)
static void GeneratePositiveLookup(MacroAssembler *masm, Label *miss, Label *done, Register elements, Register name, Register r0, Register r1)
NameDictionaryLookupStub(Isolate *isolate, Register dictionary, Register result, Register index, LookupMode mode)
DEFINE_PLATFORM_CODE_STUB(NameDictionaryLookup, PlatformCodeStub)
static void GenerateNegativeLookup(MacroAssembler *masm, Label *miss, Label *done, Register properties, Handle< Name > name, Register r0)
void SaveCallerSaveRegisters(MacroAssembler *masm, SaveFPRegsMode mode)
RegisterAllocation(Register object, Register address, Register scratch0)
Register GetRegThatIsNotEcxOr(Register r1, Register r2, Register r3)
void RestoreCallerSaveRegisters(MacroAssembler *masm, SaveFPRegsMode mode)
void GenerateIncremental(MacroAssembler *masm, Mode mode)
void InformIncrementalMarker(MacroAssembler *masm)
RememberedSetAction remembered_set_action() const
SaveFPRegsMode save_fp_regs_mode() const
RecordWriteStub(Isolate *isolate, Register object, Register value, Register address, RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode)
static const byte kTwoByteNopInstruction
RecordWriteStub(uint32_t key, Isolate *isolate)
virtual Major MajorKey() const FINAL OVERRIDE
static const byte kFiveByteJumpInstruction
void CheckNeedsToInformIncrementalMarker(MacroAssembler *masm, OnNoNeedToInformIncrementalMarker on_no_need, Mode mode)
DISALLOW_COPY_AND_ASSIGN(RecordWriteStub)
static const byte kFiveByteNopInstruction
static void Patch(Code *stub, Mode mode)
static const byte kTwoByteJumpInstruction
virtual bool SometimesSetsUpAFrame()
static Mode GetMode(Code *stub)
virtual void Generate(MacroAssembler *masm) OVERRIDE
static void GenerateCompareFlatOneByteStrings(MacroAssembler *masm, Register left, Register right, Register scratch1, Register scratch2, Register scratch3)
static void GenerateFlatOneByteStringEquals(MacroAssembler *masm, Register left, Register right, Register scratch1, Register scratch2)
static void GenerateOneByteCharsCompareLoop(MacroAssembler *masm, Register left, Register right, Register length, Register scratch, Label *chars_not_equal, Label::Distance chars_not_equal_near=Label::kFar)
DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper)
static void GenerateCopyCharacters(MacroAssembler *masm, Register dest, Register src, Register count, Register scratch, String::Encoding encoding)
#define OVERRIDE
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK(condition)
Definition: logging.h:205
const int kPointerSize
Definition: globals.h:129
const Register edx
const Register r2
bool AreAliased(const CPURegister &reg1, const CPURegister &reg2, const CPURegister &reg3=NoReg, const CPURegister &reg4=NoReg, const CPURegister &reg5=NoReg, const CPURegister &reg6=NoReg, const CPURegister &reg7=NoReg, const CPURegister &reg8=NoReg)
const Register esp
const Register r0
const Register r3
void ArrayNativeCode(MacroAssembler *masm, Label *call_generic_code)
const Register eax
const Register r1
const Register no_reg
const Register ecx
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
static Register from_code(int code)
static Register FromAllocationIndex(int index)
bool is(Register reg) const
static int NumAllocatableRegisters()