~evarlast/ubuntu/utopic/mongodb/upstart-workaround-debian-bug-718702

« back to all changes in this revision

Viewing changes to src/third_party/v8/src/ia32/code-stubs-ia32.h

  • Committer: Package Import Robot
  • Author(s): James Page, James Page, Robie Basak
  • Date: 2013-05-29 17:44:42 UTC
  • mfrom: (44.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20130529174442-z0a4qmoww4y0t458
Tags: 1:2.4.3-1ubuntu1
[ James Page ]
* Merge from Debian unstable, remaining changes:
  - Enable SSL support:
    + d/control: Add libssl-dev to BD's.
    + d/rules: Enabled --ssl option.
    + d/mongodb.conf: Add example SSL configuration options.
  - d/mongodb-server.mongodb.upstart: Add upstart configuration.
  - d/rules: Don't strip binaries during scons build for Ubuntu.
  - d/control: Add armhf to target archs.
  - d/p/SConscript.client.patch: fixup install of client libraries.
  - d/p/0010-install-libs-to-usr-lib-not-usr-lib64-Closes-588557.patch:
    Install libraries to lib not lib64.
* Dropped changes:
  - d/p/arm-support.patch: Included in Debian.
  - d/p/double-alignment.patch: Included in Debian.
  - d/rules,control: Debian also builds with avaliable system libraries
    now.
* Fix FTBFS due to gcc and boost upgrades in saucy:
  - d/p/0008-ignore-unused-local-typedefs.patch: Add -Wno-unused-typedefs
    to unbreak building with g++-4.8.
  - d/p/0009-boost-1.53.patch: Fixup signed/unsigned casting issue.

[ Robie Basak ]
* d/p/0011-Use-a-signed-char-to-store-BSONType-enumerations.patch: Fixup
  build failure on ARM due to missing signed'ness of char cast.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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_IA32_CODE_STUBS_IA32_H_
 
29
#define V8_IA32_CODE_STUBS_IA32_H_
 
30
 
 
31
#include "macro-assembler.h"
 
32
#include "code-stubs.h"
 
33
#include "ic-inl.h"
 
34
 
 
35
namespace v8 {
 
36
namespace internal {
 
37
 
 
38
 
 
39
// Compute a transcendental math function natively, or call the
 
40
// TranscendentalCache runtime function.
 
41
class TranscendentalCacheStub: public CodeStub {
 
42
 public:
 
43
  enum ArgumentType {
 
44
    TAGGED = 0,
 
45
    UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
 
46
  };
 
47
 
 
48
  TranscendentalCacheStub(TranscendentalCache::Type type,
 
49
                          ArgumentType argument_type)
 
50
      : type_(type), argument_type_(argument_type) {}
 
51
  void Generate(MacroAssembler* masm);
 
52
  static void GenerateOperation(MacroAssembler* masm,
 
53
                                TranscendentalCache::Type type);
 
54
 private:
 
55
  TranscendentalCache::Type type_;
 
56
  ArgumentType argument_type_;
 
57
 
 
58
  Major MajorKey() { return TranscendentalCache; }
 
59
  int MinorKey() { return type_ | argument_type_; }
 
60
  Runtime::FunctionId RuntimeFunction();
 
61
};
 
62
 
 
63
 
 
64
class StoreBufferOverflowStub: public CodeStub {
 
65
 public:
 
66
  explicit StoreBufferOverflowStub(SaveFPRegsMode save_fp)
 
67
      : save_doubles_(save_fp) { }
 
68
 
 
69
  void Generate(MacroAssembler* masm);
 
70
 
 
71
  virtual bool IsPregenerated() { return true; }
 
72
  static void GenerateFixedRegStubsAheadOfTime();
 
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 UnaryOpStub: public CodeStub {
 
84
 public:
 
85
  UnaryOpStub(Token::Value op,
 
86
              UnaryOverwriteMode mode,
 
87
              UnaryOpIC::TypeInfo operand_type = UnaryOpIC::UNINITIALIZED)
 
88
      : op_(op),
 
89
        mode_(mode),
 
90
        operand_type_(operand_type) {
 
91
  }
 
92
 
 
93
 private:
 
94
  Token::Value op_;
 
95
  UnaryOverwriteMode mode_;
 
96
 
 
97
  // Operand type information determined at runtime.
 
98
  UnaryOpIC::TypeInfo operand_type_;
 
99
 
 
100
  virtual void PrintName(StringStream* stream);
 
101
 
 
102
  class ModeBits: public BitField<UnaryOverwriteMode, 0, 1> {};
 
103
  class OpBits: public BitField<Token::Value, 1, 7> {};
 
104
  class OperandTypeInfoBits: public BitField<UnaryOpIC::TypeInfo, 8, 3> {};
 
105
 
 
106
  Major MajorKey() { return UnaryOp; }
 
107
  int MinorKey() {
 
108
    return ModeBits::encode(mode_)
 
109
           | OpBits::encode(op_)
 
110
           | OperandTypeInfoBits::encode(operand_type_);
 
111
  }
 
112
 
 
113
  // Note: A lot of the helper functions below will vanish when we use virtual
 
114
  // function instead of switch more often.
 
115
  void Generate(MacroAssembler* masm);
 
116
 
 
117
  void GenerateTypeTransition(MacroAssembler* masm);
 
118
 
 
119
  void GenerateSmiStub(MacroAssembler* masm);
 
120
  void GenerateSmiStubSub(MacroAssembler* masm);
 
121
  void GenerateSmiStubBitNot(MacroAssembler* masm);
 
122
  void GenerateSmiCodeSub(MacroAssembler* masm,
 
123
                          Label* non_smi,
 
124
                          Label* undo,
 
125
                          Label* slow,
 
126
                          Label::Distance non_smi_near = Label::kFar,
 
127
                          Label::Distance undo_near = Label::kFar,
 
128
                          Label::Distance slow_near = Label::kFar);
 
129
  void GenerateSmiCodeBitNot(MacroAssembler* masm,
 
130
                             Label* non_smi,
 
131
                             Label::Distance non_smi_near = Label::kFar);
 
132
  void GenerateSmiCodeUndo(MacroAssembler* masm);
 
133
 
 
134
  void GenerateHeapNumberStub(MacroAssembler* masm);
 
135
  void GenerateHeapNumberStubSub(MacroAssembler* masm);
 
136
  void GenerateHeapNumberStubBitNot(MacroAssembler* masm);
 
137
  void GenerateHeapNumberCodeSub(MacroAssembler* masm, Label* slow);
 
138
  void GenerateHeapNumberCodeBitNot(MacroAssembler* masm, Label* slow);
 
139
 
 
140
  void GenerateGenericStub(MacroAssembler* masm);
 
141
  void GenerateGenericStubSub(MacroAssembler* masm);
 
142
  void GenerateGenericStubBitNot(MacroAssembler* masm);
 
143
  void GenerateGenericCodeFallback(MacroAssembler* masm);
 
144
 
 
145
  virtual int GetCodeKind() { return Code::UNARY_OP_IC; }
 
146
 
 
147
  virtual InlineCacheState GetICState() {
 
148
    return UnaryOpIC::ToState(operand_type_);
 
149
  }
 
150
 
 
151
  virtual void FinishCode(Handle<Code> code) {
 
152
    code->set_unary_op_type(operand_type_);
 
153
  }
 
154
};
 
155
 
 
156
 
 
157
class BinaryOpStub: public CodeStub {
 
158
 public:
 
159
  BinaryOpStub(Token::Value op, OverwriteMode mode)
 
160
      : op_(op),
 
161
        mode_(mode),
 
162
        operands_type_(BinaryOpIC::UNINITIALIZED),
 
163
        result_type_(BinaryOpIC::UNINITIALIZED) {
 
164
    use_sse3_ = CpuFeatures::IsSupported(SSE3);
 
165
    ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
 
166
  }
 
167
 
 
168
  BinaryOpStub(
 
169
      int key,
 
170
      BinaryOpIC::TypeInfo operands_type,
 
171
      BinaryOpIC::TypeInfo result_type = BinaryOpIC::UNINITIALIZED)
 
172
      : op_(OpBits::decode(key)),
 
173
        mode_(ModeBits::decode(key)),
 
174
        use_sse3_(SSE3Bits::decode(key)),
 
175
        operands_type_(operands_type),
 
176
        result_type_(result_type) { }
 
177
 
 
178
 private:
 
179
  enum SmiCodeGenerateHeapNumberResults {
 
180
    ALLOW_HEAPNUMBER_RESULTS,
 
181
    NO_HEAPNUMBER_RESULTS
 
182
  };
 
183
 
 
184
  Token::Value op_;
 
185
  OverwriteMode mode_;
 
186
  bool use_sse3_;
 
187
 
 
188
  // Operand type information determined at runtime.
 
189
  BinaryOpIC::TypeInfo operands_type_;
 
190
  BinaryOpIC::TypeInfo result_type_;
 
191
 
 
192
  virtual void PrintName(StringStream* stream);
 
193
 
 
194
  // Minor key encoding in 16 bits RRRTTTSOOOOOOOMM.
 
195
  class ModeBits: public BitField<OverwriteMode, 0, 2> {};
 
196
  class OpBits: public BitField<Token::Value, 2, 7> {};
 
197
  class SSE3Bits: public BitField<bool, 9, 1> {};
 
198
  class OperandTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 10, 3> {};
 
199
  class ResultTypeInfoBits: public BitField<BinaryOpIC::TypeInfo, 13, 3> {};
 
200
 
 
201
  Major MajorKey() { return BinaryOp; }
 
202
  int MinorKey() {
 
203
    return OpBits::encode(op_)
 
204
           | ModeBits::encode(mode_)
 
205
           | SSE3Bits::encode(use_sse3_)
 
206
           | OperandTypeInfoBits::encode(operands_type_)
 
207
           | ResultTypeInfoBits::encode(result_type_);
 
208
  }
 
209
 
 
210
  void Generate(MacroAssembler* masm);
 
211
  void GenerateGeneric(MacroAssembler* masm);
 
212
  void GenerateSmiCode(MacroAssembler* masm,
 
213
                       Label* slow,
 
214
                       SmiCodeGenerateHeapNumberResults heapnumber_results);
 
215
  void GenerateLoadArguments(MacroAssembler* masm);
 
216
  void GenerateReturn(MacroAssembler* masm);
 
217
  void GenerateUninitializedStub(MacroAssembler* masm);
 
218
  void GenerateSmiStub(MacroAssembler* masm);
 
219
  void GenerateInt32Stub(MacroAssembler* masm);
 
220
  void GenerateHeapNumberStub(MacroAssembler* masm);
 
221
  void GenerateOddballStub(MacroAssembler* masm);
 
222
  void GenerateStringStub(MacroAssembler* masm);
 
223
  void GenerateBothStringStub(MacroAssembler* masm);
 
224
  void GenerateGenericStub(MacroAssembler* masm);
 
225
  void GenerateAddStrings(MacroAssembler* masm);
 
226
 
 
227
  void GenerateHeapResultAllocation(MacroAssembler* masm, Label* alloc_failure);
 
228
  void GenerateRegisterArgsPush(MacroAssembler* masm);
 
229
  void GenerateTypeTransition(MacroAssembler* masm);
 
230
  void GenerateTypeTransitionWithSavedArgs(MacroAssembler* masm);
 
231
 
 
232
  virtual int GetCodeKind() { return Code::BINARY_OP_IC; }
 
233
 
 
234
  virtual InlineCacheState GetICState() {
 
235
    return BinaryOpIC::ToState(operands_type_);
 
236
  }
 
237
 
 
238
  virtual void FinishCode(Handle<Code> code) {
 
239
    code->set_binary_op_type(operands_type_);
 
240
    code->set_binary_op_result_type(result_type_);
 
241
  }
 
242
 
 
243
  friend class CodeGenerator;
 
244
};
 
245
 
 
246
 
 
247
class StringHelper : public AllStatic {
 
248
 public:
 
249
  // Generate code for copying characters using a simple loop. This should only
 
250
  // be used in places where the number of characters is small and the
 
251
  // additional setup and checking in GenerateCopyCharactersREP adds too much
 
252
  // overhead. Copying of overlapping regions is not supported.
 
253
  static void GenerateCopyCharacters(MacroAssembler* masm,
 
254
                                     Register dest,
 
255
                                     Register src,
 
256
                                     Register count,
 
257
                                     Register scratch,
 
258
                                     bool ascii);
 
259
 
 
260
  // Generate code for copying characters using the rep movs instruction.
 
261
  // Copies ecx characters from esi to edi. Copying of overlapping regions is
 
262
  // not supported.
 
263
  static void GenerateCopyCharactersREP(MacroAssembler* masm,
 
264
                                        Register dest,     // Must be edi.
 
265
                                        Register src,      // Must be esi.
 
266
                                        Register count,    // Must be ecx.
 
267
                                        Register scratch,  // Neither of above.
 
268
                                        bool ascii);
 
269
 
 
270
  // Probe the symbol table for a two character string. If the string
 
271
  // requires non-standard hashing a jump to the label not_probed is
 
272
  // performed and registers c1 and c2 are preserved. In all other
 
273
  // cases they are clobbered. If the string is not found by probing a
 
274
  // jump to the label not_found is performed. This jump does not
 
275
  // guarantee that the string is not in the symbol table. If the
 
276
  // string is found the code falls through with the string in
 
277
  // register eax.
 
278
  static void GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
 
279
                                                   Register c1,
 
280
                                                   Register c2,
 
281
                                                   Register scratch1,
 
282
                                                   Register scratch2,
 
283
                                                   Register scratch3,
 
284
                                                   Label* not_probed,
 
285
                                                   Label* not_found);
 
286
 
 
287
  // Generate string hash.
 
288
  static void GenerateHashInit(MacroAssembler* masm,
 
289
                               Register hash,
 
290
                               Register character,
 
291
                               Register scratch);
 
292
  static void GenerateHashAddCharacter(MacroAssembler* masm,
 
293
                                       Register hash,
 
294
                                       Register character,
 
295
                                       Register scratch);
 
296
  static void GenerateHashGetHash(MacroAssembler* masm,
 
297
                                  Register hash,
 
298
                                  Register scratch);
 
299
 
 
300
 private:
 
301
  DISALLOW_IMPLICIT_CONSTRUCTORS(StringHelper);
 
302
};
 
303
 
 
304
 
 
305
// Flag that indicates how to generate code for the stub StringAddStub.
 
306
enum StringAddFlags {
 
307
  NO_STRING_ADD_FLAGS = 0,
 
308
  // Omit left string check in stub (left is definitely a string).
 
309
  NO_STRING_CHECK_LEFT_IN_STUB = 1 << 0,
 
310
  // Omit right string check in stub (right is definitely a string).
 
311
  NO_STRING_CHECK_RIGHT_IN_STUB = 1 << 1,
 
312
  // Omit both string checks in stub.
 
313
  NO_STRING_CHECK_IN_STUB =
 
314
      NO_STRING_CHECK_LEFT_IN_STUB | NO_STRING_CHECK_RIGHT_IN_STUB
 
315
};
 
316
 
 
317
 
 
318
class StringAddStub: public CodeStub {
 
319
 public:
 
320
  explicit StringAddStub(StringAddFlags flags) : flags_(flags) {}
 
321
 
 
322
 private:
 
323
  Major MajorKey() { return StringAdd; }
 
324
  int MinorKey() { return flags_; }
 
325
 
 
326
  void Generate(MacroAssembler* masm);
 
327
 
 
328
  void GenerateConvertArgument(MacroAssembler* masm,
 
329
                               int stack_offset,
 
330
                               Register arg,
 
331
                               Register scratch1,
 
332
                               Register scratch2,
 
333
                               Register scratch3,
 
334
                               Label* slow);
 
335
 
 
336
  const StringAddFlags flags_;
 
337
};
 
338
 
 
339
 
 
340
class SubStringStub: public CodeStub {
 
341
 public:
 
342
  SubStringStub() {}
 
343
 
 
344
 private:
 
345
  Major MajorKey() { return SubString; }
 
346
  int MinorKey() { return 0; }
 
347
 
 
348
  void Generate(MacroAssembler* masm);
 
349
};
 
350
 
 
351
 
 
352
class StringCompareStub: public CodeStub {
 
353
 public:
 
354
  StringCompareStub() { }
 
355
 
 
356
  // Compares two flat ASCII strings and returns result in eax.
 
357
  static void GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
 
358
                                              Register left,
 
359
                                              Register right,
 
360
                                              Register scratch1,
 
361
                                              Register scratch2,
 
362
                                              Register scratch3);
 
363
 
 
364
  // Compares two flat ASCII strings for equality and returns result
 
365
  // in eax.
 
366
  static void GenerateFlatAsciiStringEquals(MacroAssembler* masm,
 
367
                                            Register left,
 
368
                                            Register right,
 
369
                                            Register scratch1,
 
370
                                            Register scratch2);
 
371
 
 
372
 private:
 
373
  virtual Major MajorKey() { return StringCompare; }
 
374
  virtual int MinorKey() { return 0; }
 
375
  virtual void Generate(MacroAssembler* masm);
 
376
 
 
377
  static void GenerateAsciiCharsCompareLoop(
 
378
      MacroAssembler* masm,
 
379
      Register left,
 
380
      Register right,
 
381
      Register length,
 
382
      Register scratch,
 
383
      Label* chars_not_equal,
 
384
      Label::Distance chars_not_equal_near = Label::kFar);
 
385
};
 
386
 
 
387
 
 
388
class NumberToStringStub: public CodeStub {
 
389
 public:
 
390
  NumberToStringStub() { }
 
391
 
 
392
  // Generate code to do a lookup in the number string cache. If the number in
 
393
  // the register object is found in the cache the generated code falls through
 
394
  // with the result in the result register. The object and the result register
 
395
  // can be the same. If the number is not found in the cache the code jumps to
 
396
  // the label not_found with only the content of register object unchanged.
 
397
  static void GenerateLookupNumberStringCache(MacroAssembler* masm,
 
398
                                              Register object,
 
399
                                              Register result,
 
400
                                              Register scratch1,
 
401
                                              Register scratch2,
 
402
                                              bool object_is_smi,
 
403
                                              Label* not_found);
 
404
 
 
405
 private:
 
406
  Major MajorKey() { return NumberToString; }
 
407
  int MinorKey() { return 0; }
 
408
 
 
409
  void Generate(MacroAssembler* masm);
 
410
};
 
411
 
 
412
 
 
413
class StringDictionaryLookupStub: public CodeStub {
 
414
 public:
 
415
  enum LookupMode { POSITIVE_LOOKUP, NEGATIVE_LOOKUP };
 
416
 
 
417
  StringDictionaryLookupStub(Register dictionary,
 
418
                             Register result,
 
419
                             Register index,
 
420
                             LookupMode mode)
 
421
      : dictionary_(dictionary), result_(result), index_(index), mode_(mode) { }
 
422
 
 
423
  void Generate(MacroAssembler* masm);
 
424
 
 
425
  static void GenerateNegativeLookup(MacroAssembler* masm,
 
426
                                     Label* miss,
 
427
                                     Label* done,
 
428
                                     Register properties,
 
429
                                     Handle<String> name,
 
430
                                     Register r0);
 
431
 
 
432
  static void GeneratePositiveLookup(MacroAssembler* masm,
 
433
                                     Label* miss,
 
434
                                     Label* done,
 
435
                                     Register elements,
 
436
                                     Register name,
 
437
                                     Register r0,
 
438
                                     Register r1);
 
439
 
 
440
  virtual bool SometimesSetsUpAFrame() { return false; }
 
441
 
 
442
 private:
 
443
  static const int kInlinedProbes = 4;
 
444
  static const int kTotalProbes = 20;
 
445
 
 
446
  static const int kCapacityOffset =
 
447
      StringDictionary::kHeaderSize +
 
448
      StringDictionary::kCapacityIndex * kPointerSize;
 
449
 
 
450
  static const int kElementsStartOffset =
 
451
      StringDictionary::kHeaderSize +
 
452
      StringDictionary::kElementsStartIndex * kPointerSize;
 
453
 
 
454
  Major MajorKey() { return StringDictionaryLookup; }
 
455
 
 
456
  int MinorKey() {
 
457
    return DictionaryBits::encode(dictionary_.code()) |
 
458
        ResultBits::encode(result_.code()) |
 
459
        IndexBits::encode(index_.code()) |
 
460
        LookupModeBits::encode(mode_);
 
461
  }
 
462
 
 
463
  class DictionaryBits: public BitField<int, 0, 3> {};
 
464
  class ResultBits: public BitField<int, 3, 3> {};
 
465
  class IndexBits: public BitField<int, 6, 3> {};
 
466
  class LookupModeBits: public BitField<LookupMode, 9, 1> {};
 
467
 
 
468
  Register dictionary_;
 
469
  Register result_;
 
470
  Register index_;
 
471
  LookupMode mode_;
 
472
};
 
473
 
 
474
 
 
475
class RecordWriteStub: public CodeStub {
 
476
 public:
 
477
  RecordWriteStub(Register object,
 
478
                  Register value,
 
479
                  Register address,
 
480
                  RememberedSetAction remembered_set_action,
 
481
                  SaveFPRegsMode fp_mode)
 
482
      : object_(object),
 
483
        value_(value),
 
484
        address_(address),
 
485
        remembered_set_action_(remembered_set_action),
 
486
        save_fp_regs_mode_(fp_mode),
 
487
        regs_(object,   // An input reg.
 
488
              address,  // An input reg.
 
489
              value) {  // One scratch reg.
 
490
  }
 
491
 
 
492
  enum Mode {
 
493
    STORE_BUFFER_ONLY,
 
494
    INCREMENTAL,
 
495
    INCREMENTAL_COMPACTION
 
496
  };
 
497
 
 
498
  virtual bool IsPregenerated();
 
499
  static void GenerateFixedRegStubsAheadOfTime();
 
500
  virtual bool SometimesSetsUpAFrame() { return false; }
 
501
 
 
502
  static const byte kTwoByteNopInstruction = 0x3c;  // Cmpb al, #imm8.
 
503
  static const byte kTwoByteJumpInstruction = 0xeb;  // Jmp #imm8.
 
504
 
 
505
  static const byte kFiveByteNopInstruction = 0x3d;  // Cmpl eax, #imm32.
 
506
  static const byte kFiveByteJumpInstruction = 0xe9;  // Jmp #imm32.
 
507
 
 
508
  static Mode GetMode(Code* stub) {
 
509
    byte first_instruction = stub->instruction_start()[0];
 
510
    byte second_instruction = stub->instruction_start()[2];
 
511
 
 
512
    if (first_instruction == kTwoByteJumpInstruction) {
 
513
      return INCREMENTAL;
 
514
    }
 
515
 
 
516
    ASSERT(first_instruction == kTwoByteNopInstruction);
 
517
 
 
518
    if (second_instruction == kFiveByteJumpInstruction) {
 
519
      return INCREMENTAL_COMPACTION;
 
520
    }
 
521
 
 
522
    ASSERT(second_instruction == kFiveByteNopInstruction);
 
523
 
 
524
    return STORE_BUFFER_ONLY;
 
525
  }
 
526
 
 
527
  static void Patch(Code* stub, Mode mode) {
 
528
    switch (mode) {
 
529
      case STORE_BUFFER_ONLY:
 
530
        ASSERT(GetMode(stub) == INCREMENTAL ||
 
531
               GetMode(stub) == INCREMENTAL_COMPACTION);
 
532
        stub->instruction_start()[0] = kTwoByteNopInstruction;
 
533
        stub->instruction_start()[2] = kFiveByteNopInstruction;
 
534
        break;
 
535
      case INCREMENTAL:
 
536
        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
 
537
        stub->instruction_start()[0] = kTwoByteJumpInstruction;
 
538
        break;
 
539
      case INCREMENTAL_COMPACTION:
 
540
        ASSERT(GetMode(stub) == STORE_BUFFER_ONLY);
 
541
        stub->instruction_start()[0] = kTwoByteNopInstruction;
 
542
        stub->instruction_start()[2] = kFiveByteJumpInstruction;
 
543
        break;
 
544
    }
 
545
    ASSERT(GetMode(stub) == mode);
 
546
    CPU::FlushICache(stub->instruction_start(), 7);
 
547
  }
 
548
 
 
549
 private:
 
550
  // This is a helper class for freeing up 3 scratch registers, where the third
 
551
  // is always ecx (needed for shift operations).  The input is two registers
 
552
  // that must be preserved and one scratch register provided by the caller.
 
553
  class RegisterAllocation {
 
554
   public:
 
555
    RegisterAllocation(Register object,
 
556
                       Register address,
 
557
                       Register scratch0)
 
558
        : object_orig_(object),
 
559
          address_orig_(address),
 
560
          scratch0_orig_(scratch0),
 
561
          object_(object),
 
562
          address_(address),
 
563
          scratch0_(scratch0) {
 
564
      ASSERT(!AreAliased(scratch0, object, address, no_reg));
 
565
      scratch1_ = GetRegThatIsNotEcxOr(object_, address_, scratch0_);
 
566
      if (scratch0.is(ecx)) {
 
567
        scratch0_ = GetRegThatIsNotEcxOr(object_, address_, scratch1_);
 
568
      }
 
569
      if (object.is(ecx)) {
 
570
        object_ = GetRegThatIsNotEcxOr(address_, scratch0_, scratch1_);
 
571
      }
 
572
      if (address.is(ecx)) {
 
573
        address_ = GetRegThatIsNotEcxOr(object_, scratch0_, scratch1_);
 
574
      }
 
575
      ASSERT(!AreAliased(scratch0_, object_, address_, ecx));
 
576
    }
 
577
 
 
578
    void Save(MacroAssembler* masm) {
 
579
      ASSERT(!address_orig_.is(object_));
 
580
      ASSERT(object_.is(object_orig_) || address_.is(address_orig_));
 
581
      ASSERT(!AreAliased(object_, address_, scratch1_, scratch0_));
 
582
      ASSERT(!AreAliased(object_orig_, address_, scratch1_, scratch0_));
 
583
      ASSERT(!AreAliased(object_, address_orig_, scratch1_, scratch0_));
 
584
      // We don't have to save scratch0_orig_ because it was given to us as
 
585
      // a scratch register.  But if we had to switch to a different reg then
 
586
      // we should save the new scratch0_.
 
587
      if (!scratch0_.is(scratch0_orig_)) masm->push(scratch0_);
 
588
      if (!ecx.is(scratch0_orig_) &&
 
589
          !ecx.is(object_orig_) &&
 
590
          !ecx.is(address_orig_)) {
 
591
        masm->push(ecx);
 
592
      }
 
593
      masm->push(scratch1_);
 
594
      if (!address_.is(address_orig_)) {
 
595
        masm->push(address_);
 
596
        masm->mov(address_, address_orig_);
 
597
      }
 
598
      if (!object_.is(object_orig_)) {
 
599
        masm->push(object_);
 
600
        masm->mov(object_, object_orig_);
 
601
      }
 
602
    }
 
603
 
 
604
    void Restore(MacroAssembler* masm) {
 
605
      // These will have been preserved the entire time, so we just need to move
 
606
      // them back.  Only in one case is the orig_ reg different from the plain
 
607
      // one, since only one of them can alias with ecx.
 
608
      if (!object_.is(object_orig_)) {
 
609
        masm->mov(object_orig_, object_);
 
610
        masm->pop(object_);
 
611
      }
 
612
      if (!address_.is(address_orig_)) {
 
613
        masm->mov(address_orig_, address_);
 
614
        masm->pop(address_);
 
615
      }
 
616
      masm->pop(scratch1_);
 
617
      if (!ecx.is(scratch0_orig_) &&
 
618
          !ecx.is(object_orig_) &&
 
619
          !ecx.is(address_orig_)) {
 
620
        masm->pop(ecx);
 
621
      }
 
622
      if (!scratch0_.is(scratch0_orig_)) masm->pop(scratch0_);
 
623
    }
 
624
 
 
625
    // If we have to call into C then we need to save and restore all caller-
 
626
    // saved registers that were not already preserved.  The caller saved
 
627
    // registers are eax, ecx and edx.  The three scratch registers (incl. ecx)
 
628
    // will be restored by other means so we don't bother pushing them here.
 
629
    void SaveCallerSaveRegisters(MacroAssembler* masm, SaveFPRegsMode mode) {
 
630
      if (!scratch0_.is(eax) && !scratch1_.is(eax)) masm->push(eax);
 
631
      if (!scratch0_.is(edx) && !scratch1_.is(edx)) masm->push(edx);
 
632
      if (mode == kSaveFPRegs) {
 
633
        CpuFeatures::Scope scope(SSE2);
 
634
        masm->sub(esp,
 
635
                  Immediate(kDoubleSize * (XMMRegister::kNumRegisters - 1)));
 
636
        // Save all XMM registers except XMM0.
 
637
        for (int i = XMMRegister::kNumRegisters - 1; i > 0; i--) {
 
638
          XMMRegister reg = XMMRegister::from_code(i);
 
639
          masm->movdbl(Operand(esp, (i - 1) * kDoubleSize), reg);
 
640
        }
 
641
      }
 
642
    }
 
643
 
 
644
    inline void RestoreCallerSaveRegisters(MacroAssembler*masm,
 
645
                                           SaveFPRegsMode mode) {
 
646
      if (mode == kSaveFPRegs) {
 
647
        CpuFeatures::Scope scope(SSE2);
 
648
        // Restore all XMM registers except XMM0.
 
649
        for (int i = XMMRegister::kNumRegisters - 1; i > 0; i--) {
 
650
          XMMRegister reg = XMMRegister::from_code(i);
 
651
          masm->movdbl(reg, Operand(esp, (i - 1) * kDoubleSize));
 
652
        }
 
653
        masm->add(esp,
 
654
                  Immediate(kDoubleSize * (XMMRegister::kNumRegisters - 1)));
 
655
      }
 
656
      if (!scratch0_.is(edx) && !scratch1_.is(edx)) masm->pop(edx);
 
657
      if (!scratch0_.is(eax) && !scratch1_.is(eax)) masm->pop(eax);
 
658
    }
 
659
 
 
660
    inline Register object() { return object_; }
 
661
    inline Register address() { return address_; }
 
662
    inline Register scratch0() { return scratch0_; }
 
663
    inline Register scratch1() { return scratch1_; }
 
664
 
 
665
   private:
 
666
    Register object_orig_;
 
667
    Register address_orig_;
 
668
    Register scratch0_orig_;
 
669
    Register object_;
 
670
    Register address_;
 
671
    Register scratch0_;
 
672
    Register scratch1_;
 
673
    // Third scratch register is always ecx.
 
674
 
 
675
    Register GetRegThatIsNotEcxOr(Register r1,
 
676
                                  Register r2,
 
677
                                  Register r3) {
 
678
      for (int i = 0; i < Register::kNumAllocatableRegisters; i++) {
 
679
        Register candidate = Register::FromAllocationIndex(i);
 
680
        if (candidate.is(ecx)) continue;
 
681
        if (candidate.is(r1)) continue;
 
682
        if (candidate.is(r2)) continue;
 
683
        if (candidate.is(r3)) continue;
 
684
        return candidate;
 
685
      }
 
686
      UNREACHABLE();
 
687
      return no_reg;
 
688
    }
 
689
    friend class RecordWriteStub;
 
690
  };
 
691
 
 
692
  enum OnNoNeedToInformIncrementalMarker {
 
693
    kReturnOnNoNeedToInformIncrementalMarker,
 
694
    kUpdateRememberedSetOnNoNeedToInformIncrementalMarker
 
695
  }
 
696
;
 
697
  void Generate(MacroAssembler* masm);
 
698
  void GenerateIncremental(MacroAssembler* masm, Mode mode);
 
699
  void CheckNeedsToInformIncrementalMarker(
 
700
      MacroAssembler* masm,
 
701
      OnNoNeedToInformIncrementalMarker on_no_need,
 
702
      Mode mode);
 
703
  void InformIncrementalMarker(MacroAssembler* masm, Mode mode);
 
704
 
 
705
  Major MajorKey() { return RecordWrite; }
 
706
 
 
707
  int MinorKey() {
 
708
    return ObjectBits::encode(object_.code()) |
 
709
        ValueBits::encode(value_.code()) |
 
710
        AddressBits::encode(address_.code()) |
 
711
        RememberedSetActionBits::encode(remembered_set_action_) |
 
712
        SaveFPRegsModeBits::encode(save_fp_regs_mode_);
 
713
  }
 
714
 
 
715
  void Activate(Code* code) {
 
716
    code->GetHeap()->incremental_marking()->ActivateGeneratedStub(code);
 
717
  }
 
718
 
 
719
  class ObjectBits: public BitField<int, 0, 3> {};
 
720
  class ValueBits: public BitField<int, 3, 3> {};
 
721
  class AddressBits: public BitField<int, 6, 3> {};
 
722
  class RememberedSetActionBits: public BitField<RememberedSetAction, 9, 1> {};
 
723
  class SaveFPRegsModeBits: public BitField<SaveFPRegsMode, 10, 1> {};
 
724
 
 
725
  Register object_;
 
726
  Register value_;
 
727
  Register address_;
 
728
  RememberedSetAction remembered_set_action_;
 
729
  SaveFPRegsMode save_fp_regs_mode_;
 
730
  RegisterAllocation regs_;
 
731
};
 
732
 
 
733
 
 
734
} }  // namespace v8::internal
 
735
 
 
736
#endif  // V8_IA32_CODE_STUBS_IA32_H_