~ubuntu-branches/ubuntu/trusty/libv8/trusty

« back to all changes in this revision

Viewing changes to src/code-stubs.h

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2012-02-20 14:08:17 UTC
  • mfrom: (15.1.24 sid)
  • Revision ID: package-import@ubuntu.com-20120220140817-bsvmeoa4sxsj5hbz
Tags: 3.7.12.22-3
Fix mipsel build, allow test debug-step-3 to fail (non-crucial)

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
 
31
31
#include "allocation.h"
32
32
#include "globals.h"
 
33
#include "codegen.h"
33
34
 
34
35
namespace v8 {
35
36
namespace internal {
45
46
  V(Compare)                             \
46
47
  V(CompareIC)                           \
47
48
  V(MathPow)                             \
 
49
  V(RecordWrite)                         \
 
50
  V(StoreBufferOverflow)                 \
 
51
  V(RegExpExec)                          \
48
52
  V(TranscendentalCache)                 \
49
53
  V(Instanceof)                          \
50
 
  /* All stubs above this line only exist in a few versions, which are  */  \
51
 
  /* generated ahead of time.  Therefore compiling a call to one of     */  \
52
 
  /* them can't cause a new stub to be compiled, so compiling a call to */  \
53
 
  /* them is GC safe.  The ones below this line exist in many variants  */  \
54
 
  /* so code compiling a call to one can cause a GC.  This means they   */  \
55
 
  /* can't be called from other stubs, since stub generation code is    */  \
56
 
  /* not GC safe.                                                       */  \
57
54
  V(ConvertToDouble)                     \
58
55
  V(WriteInt32ToHeapNumber)              \
59
56
  V(StackCheck)                          \
60
57
  V(FastNewClosure)                      \
61
58
  V(FastNewContext)                      \
 
59
  V(FastNewBlockContext)                 \
62
60
  V(FastCloneShallowArray)               \
63
 
  V(RevertToNumber)                      \
 
61
  V(FastCloneShallowObject)              \
64
62
  V(ToBoolean)                           \
65
63
  V(ToNumber)                            \
66
 
  V(CounterOp)                           \
67
64
  V(ArgumentsAccess)                     \
68
 
  V(RegExpExec)                          \
69
65
  V(RegExpConstructResult)               \
70
66
  V(NumberToString)                      \
71
67
  V(CEntry)                              \
73
69
  V(KeyedLoadElement)                    \
74
70
  V(KeyedStoreElement)                   \
75
71
  V(DebuggerStatement)                   \
76
 
  V(StringDictionaryNegativeLookup)
 
72
  V(StringDictionaryLookup)              \
 
73
  V(ElementsTransitionAndStore)          \
 
74
  V(StoreArrayLiteralElement)
77
75
 
78
76
// List of code stubs only used on ARM platforms.
79
77
#ifdef V8_TARGET_ARCH_ARM
121
119
  // Retrieve the code for the stub. Generate the code if needed.
122
120
  Handle<Code> GetCode();
123
121
 
124
 
  // Retrieve the code for the stub if already generated.  Do not
125
 
  // generate the code if not already generated and instead return a
126
 
  // retry after GC Failure object.
127
 
  MUST_USE_RESULT MaybeObject* TryGetCode();
128
 
 
129
122
  static Major MajorKeyFromKey(uint32_t key) {
130
123
    return static_cast<Major>(MajorKeyBits::decode(key));
131
124
  }
142
135
 
143
136
  virtual ~CodeStub() {}
144
137
 
 
138
  bool CompilingCallsToThisStubIsGCSafe() {
 
139
    bool is_pregenerated = IsPregenerated();
 
140
    Code* code = NULL;
 
141
    CHECK(!is_pregenerated || FindCodeInCache(&code));
 
142
    return is_pregenerated;
 
143
  }
 
144
 
 
145
  // See comment above, where Instanceof is defined.
 
146
  virtual bool IsPregenerated() { return false; }
 
147
 
 
148
  static void GenerateStubsAheadOfTime();
 
149
  static void GenerateFPStubs();
 
150
 
 
151
  // Some stubs put untagged junk on the stack that cannot be scanned by the
 
152
  // GC.  This means that we must be statically sure that no GC can occur while
 
153
  // they are running.  If that is the case they should override this to return
 
154
  // true, which will cause an assertion if we try to call something that can
 
155
  // GC or if we try to put a stack frame on top of the junk, which would not
 
156
  // result in a traversable stack.
 
157
  virtual bool SometimesSetsUpAFrame() { return true; }
 
158
 
 
159
  // Lookup the code in the (possibly custom) cache.
 
160
  bool FindCodeInCache(Code** code_out);
 
161
 
145
162
 protected:
146
163
  static const int kMajorBits = 6;
147
164
  static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits;
148
165
 
149
166
 private:
150
 
  // Lookup the code in the (possibly custom) cache.
151
 
  bool FindCodeInCache(Code** code_out);
152
 
 
153
167
  // Nonvirtual wrapper around the stub-specific Generate function.  Call
154
168
  // this function to set up the macro assembler and generate the code.
155
169
  void GenerateCode(MacroAssembler* masm);
162
176
  void RecordCodeGeneration(Code* code, MacroAssembler* masm);
163
177
 
164
178
  // Finish the code object after it has been generated.
165
 
  virtual void FinishCode(Code* code) { }
 
179
  virtual void FinishCode(Handle<Code> code) { }
 
180
 
 
181
  // Activate newly generated stub. Is called after
 
182
  // registering stub in the stub cache.
 
183
  virtual void Activate(Code* code) { }
166
184
 
167
185
  // Returns information for computing the number key.
168
186
  virtual Major MajorKey() = 0;
178
196
 
179
197
  // Returns a name for logging/debugging purposes.
180
198
  SmartArrayPointer<const char> GetName();
181
 
  virtual void PrintName(StringStream* stream) {
182
 
    stream->Add("%s", MajorName(MajorKey(), false));
183
 
  }
 
199
  virtual void PrintName(StringStream* stream);
184
200
 
185
201
  // Returns whether the code generated for this stub needs to be allocated as
186
202
  // a fixed (non-moveable) code object.
193
209
           MajorKeyBits::encode(MajorKey());
194
210
  }
195
211
 
196
 
  // See comment above, where Instanceof is defined.
197
 
  bool AllowsStubCalls() { return MajorKey() <= Instanceof; }
198
 
 
199
212
  class MajorKeyBits: public BitField<uint32_t, 0, kMajorBits> {};
200
213
  class MinorKeyBits: public BitField<uint32_t, kMajorBits, kMinorBits> {};
201
214
 
286
299
 
287
300
class FastNewClosureStub : public CodeStub {
288
301
 public:
289
 
  explicit FastNewClosureStub(StrictModeFlag strict_mode)
290
 
    : strict_mode_(strict_mode) { }
 
302
  explicit FastNewClosureStub(LanguageMode language_mode)
 
303
    : language_mode_(language_mode) { }
291
304
 
292
305
  void Generate(MacroAssembler* masm);
293
306
 
294
307
 private:
295
308
  Major MajorKey() { return FastNewClosure; }
296
 
  int MinorKey() { return strict_mode_; }
 
309
  int MinorKey() { return language_mode_ == CLASSIC_MODE
 
310
        ? kNonStrictMode : kStrictMode; }
297
311
 
298
 
  StrictModeFlag strict_mode_;
 
312
  LanguageMode language_mode_;
299
313
};
300
314
 
301
315
 
304
318
  static const int kMaximumSlots = 64;
305
319
 
306
320
  explicit FastNewContextStub(int slots) : slots_(slots) {
307
 
    ASSERT(slots_ > 0 && slots <= kMaximumSlots);
 
321
    ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
308
322
  }
309
323
 
310
324
  void Generate(MacroAssembler* masm);
317
331
};
318
332
 
319
333
 
 
334
class FastNewBlockContextStub : public CodeStub {
 
335
 public:
 
336
  static const int kMaximumSlots = 64;
 
337
 
 
338
  explicit FastNewBlockContextStub(int slots) : slots_(slots) {
 
339
    ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
 
340
  }
 
341
 
 
342
  void Generate(MacroAssembler* masm);
 
343
 
 
344
 private:
 
345
  int slots_;
 
346
 
 
347
  Major MajorKey() { return FastNewBlockContext; }
 
348
  int MinorKey() { return slots_; }
 
349
};
 
350
 
 
351
 
320
352
class FastCloneShallowArrayStub : public CodeStub {
321
353
 public:
322
354
  // Maximum length of copied elements array.
324
356
 
325
357
  enum Mode {
326
358
    CLONE_ELEMENTS,
327
 
    COPY_ON_WRITE_ELEMENTS
 
359
    CLONE_DOUBLE_ELEMENTS,
 
360
    COPY_ON_WRITE_ELEMENTS,
 
361
    CLONE_ANY_ELEMENTS
328
362
  };
329
363
 
330
364
  FastCloneShallowArrayStub(Mode mode, int length)
331
365
      : mode_(mode),
332
366
        length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
333
 
    ASSERT(length_ >= 0);
334
 
    ASSERT(length_ <= kMaximumClonedLength);
 
367
    ASSERT_GE(length_, 0);
 
368
    ASSERT_LE(length_, kMaximumClonedLength);
335
369
  }
336
370
 
337
371
  void Generate(MacroAssembler* masm);
342
376
 
343
377
  Major MajorKey() { return FastCloneShallowArray; }
344
378
  int MinorKey() {
345
 
    ASSERT(mode_ == 0 || mode_ == 1);
346
 
    return (length_ << 1) | mode_;
347
 
  }
 
379
    ASSERT(mode_ == 0 || mode_ == 1 || mode_ == 2 || mode_ == 3);
 
380
    return length_ * 4 +  mode_;
 
381
  }
 
382
};
 
383
 
 
384
 
 
385
class FastCloneShallowObjectStub : public CodeStub {
 
386
 public:
 
387
  // Maximum number of properties in copied object.
 
388
  static const int kMaximumClonedProperties = 6;
 
389
 
 
390
  explicit FastCloneShallowObjectStub(int length) : length_(length) {
 
391
    ASSERT_GE(length_, 0);
 
392
    ASSERT_LE(length_, kMaximumClonedProperties);
 
393
  }
 
394
 
 
395
  void Generate(MacroAssembler* masm);
 
396
 
 
397
 private:
 
398
  int length_;
 
399
 
 
400
  Major MajorKey() { return FastCloneShallowObject; }
 
401
  int MinorKey() { return length_; }
348
402
};
349
403
 
350
404
 
410
464
  class OpField: public BitField<int, 0, 3> { };
411
465
  class StateField: public BitField<int, 3, 5> { };
412
466
 
413
 
  virtual void FinishCode(Code* code) { code->set_compare_state(state_); }
 
467
  virtual void FinishCode(Handle<Code> code) {
 
468
    code->set_compare_state(state_);
 
469
  }
414
470
 
415
471
  virtual CodeStub::Major MajorKey() { return CompareIC; }
416
472
  virtual int MinorKey();
513
569
  int MinorKey();
514
570
 
515
571
  virtual int GetCodeKind() { return Code::COMPARE_IC; }
516
 
  virtual void FinishCode(Code* code) {
 
572
  virtual void FinishCode(Handle<Code> code) {
517
573
    code->set_compare_state(CompareIC::GENERIC);
518
574
  }
519
575
 
531
587
 
532
588
class CEntryStub : public CodeStub {
533
589
 public:
534
 
  explicit CEntryStub(int result_size)
535
 
      : result_size_(result_size), save_doubles_(false) { }
 
590
  explicit CEntryStub(int result_size,
 
591
                      SaveFPRegsMode save_doubles = kDontSaveFPRegs)
 
592
      : result_size_(result_size), save_doubles_(save_doubles) { }
536
593
 
537
594
  void Generate(MacroAssembler* masm);
538
 
  void SaveDoubles() { save_doubles_ = true; }
 
595
 
 
596
  // The version of this stub that doesn't save doubles is generated ahead of
 
597
  // time, so it's OK to call it from other stubs that can't cope with GC during
 
598
  // their code generation.  On machines that always have gp registers (x64) we
 
599
  // can generate both variants ahead of time.
 
600
  virtual bool IsPregenerated();
 
601
  static void GenerateAheadOfTime();
539
602
 
540
603
 private:
541
604
  void GenerateCore(MacroAssembler* masm,
550
613
 
551
614
  // Number of pointers/values returned.
552
615
  const int result_size_;
553
 
  bool save_doubles_;
 
616
  SaveFPRegsMode save_doubles_;
554
617
 
555
618
  Major MajorKey() { return CEntry; }
556
619
  int MinorKey();
571
634
 private:
572
635
  Major MajorKey() { return JSEntry; }
573
636
  int MinorKey() { return 0; }
 
637
 
 
638
  virtual void FinishCode(Handle<Code> code);
 
639
 
 
640
  int handler_offset_;
574
641
};
575
642
 
576
643
 
647
714
 
648
715
  void Generate(MacroAssembler* masm);
649
716
 
 
717
  virtual void FinishCode(Handle<Code> code);
 
718
 
 
719
  static void Clear(Heap* heap, Address address);
 
720
 
 
721
  static Object* GetCachedValue(Address address);
 
722
 
650
723
  static int ExtractArgcFromMinorKey(int minor_key) {
651
724
    return ArgcBits::decode(minor_key);
652
725
  }
653
726
 
 
727
  // The object that indicates an uninitialized cache.
 
728
  static Handle<Object> UninitializedSentinel(Isolate* isolate) {
 
729
    return isolate->factory()->the_hole_value();
 
730
  }
 
731
 
 
732
  // A raw version of the uninitialized sentinel that's safe to read during
 
733
  // garbage collection (e.g., for patching the cache).
 
734
  static Object* RawUninitializedSentinel(Heap* heap) {
 
735
    return heap->raw_unchecked_the_hole_value();
 
736
  }
 
737
 
 
738
  // The object that indicates a megamorphic state.
 
739
  static Handle<Object> MegamorphicSentinel(Isolate* isolate) {
 
740
    return isolate->factory()->undefined_value();
 
741
  }
 
742
 
654
743
 private:
655
744
  int argc_;
656
745
  CallFunctionFlags flags_;
658
747
  virtual void PrintName(StringStream* stream);
659
748
 
660
749
  // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
661
 
  class FlagBits: public BitField<CallFunctionFlags, 0, 1> {};
662
 
  class ArgcBits: public BitField<unsigned, 1, 32 - 1> {};
 
750
  class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
 
751
  class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
663
752
 
664
753
  Major MajorKey() { return CallFunction; }
665
754
  int MinorKey() {
670
759
  bool ReceiverMightBeImplicit() {
671
760
    return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0;
672
761
  }
 
762
 
 
763
  bool RecordCallTarget() {
 
764
    return (flags_ & RECORD_CALL_TARGET) != 0;
 
765
  }
673
766
};
674
767
 
675
768
 
698
791
 public:
699
792
  StringCharCodeAtGenerator(Register object,
700
793
                            Register index,
701
 
                            Register scratch,
702
794
                            Register result,
703
795
                            Label* receiver_not_string,
704
796
                            Label* index_not_number,
706
798
                            StringIndexFlags index_flags)
707
799
      : object_(object),
708
800
        index_(index),
709
 
        scratch_(scratch),
710
801
        result_(result),
711
802
        receiver_not_string_(receiver_not_string),
712
803
        index_not_number_(index_not_number),
713
804
        index_out_of_range_(index_out_of_range),
714
805
        index_flags_(index_flags) {
715
 
    ASSERT(!scratch_.is(object_));
716
 
    ASSERT(!scratch_.is(index_));
717
 
    ASSERT(!scratch_.is(result_));
718
806
    ASSERT(!result_.is(object_));
719
807
    ASSERT(!result_.is(index_));
720
808
  }
732
820
 private:
733
821
  Register object_;
734
822
  Register index_;
735
 
  Register scratch_;
736
823
  Register result_;
737
824
 
738
825
  Label* receiver_not_string_;
795
882
 public:
796
883
  StringCharAtGenerator(Register object,
797
884
                        Register index,
798
 
                        Register scratch1,
799
 
                        Register scratch2,
 
885
                        Register scratch,
800
886
                        Register result,
801
887
                        Label* receiver_not_string,
802
888
                        Label* index_not_number,
804
890
                        StringIndexFlags index_flags)
805
891
      : char_code_at_generator_(object,
806
892
                                index,
807
 
                                scratch1,
808
 
                                scratch2,
 
893
                                scratch,
809
894
                                receiver_not_string,
810
895
                                index_not_number,
811
896
                                index_out_of_range,
812
897
                                index_flags),
813
 
        char_from_code_generator_(scratch2, result) {}
 
898
        char_from_code_generator_(scratch, result) {}
814
899
 
815
900
  // Generates the fast case code. On the fallthrough path |result|
816
901
  // register contains the result.
934
1019
  virtual int GetCodeKind() { return Code::TO_BOOLEAN_IC; }
935
1020
  virtual void PrintName(StringStream* stream);
936
1021
 
 
1022
  virtual bool SometimesSetsUpAFrame() { return false; }
 
1023
 
937
1024
 private:
938
1025
  Major MajorKey() { return ToBoolean; }
939
1026
  int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | types_.ToByte(); }
940
1027
 
941
 
  virtual void FinishCode(Code* code) {
 
1028
  virtual void FinishCode(Handle<Code> code) {
942
1029
    code->set_to_boolean_state(types_.ToByte());
943
1030
  }
944
1031
 
952
1039
  Types types_;
953
1040
};
954
1041
 
 
1042
 
 
1043
class ElementsTransitionAndStoreStub : public CodeStub {
 
1044
 public:
 
1045
  ElementsTransitionAndStoreStub(ElementsKind from,
 
1046
                                 ElementsKind to,
 
1047
                                 bool is_jsarray,
 
1048
                                 StrictModeFlag strict_mode)
 
1049
      : from_(from),
 
1050
        to_(to),
 
1051
        is_jsarray_(is_jsarray),
 
1052
        strict_mode_(strict_mode) {}
 
1053
 
 
1054
 private:
 
1055
  class FromBits:       public BitField<ElementsKind,    0, 8> {};
 
1056
  class ToBits:         public BitField<ElementsKind,    8, 8> {};
 
1057
  class IsJSArrayBits:  public BitField<bool,           16, 8> {};
 
1058
  class StrictModeBits: public BitField<StrictModeFlag, 24, 8> {};
 
1059
 
 
1060
  Major MajorKey() { return ElementsTransitionAndStore; }
 
1061
  int MinorKey() {
 
1062
    return FromBits::encode(from_) |
 
1063
        ToBits::encode(to_) |
 
1064
        IsJSArrayBits::encode(is_jsarray_) |
 
1065
        StrictModeBits::encode(strict_mode_);
 
1066
  }
 
1067
 
 
1068
  void Generate(MacroAssembler* masm);
 
1069
 
 
1070
  ElementsKind from_;
 
1071
  ElementsKind to_;
 
1072
  bool is_jsarray_;
 
1073
  StrictModeFlag strict_mode_;
 
1074
 
 
1075
  DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
 
1076
};
 
1077
 
 
1078
 
 
1079
class StoreArrayLiteralElementStub : public CodeStub {
 
1080
 public:
 
1081
  explicit StoreArrayLiteralElementStub() {}
 
1082
 
 
1083
 private:
 
1084
  Major MajorKey() { return StoreArrayLiteralElement; }
 
1085
  int MinorKey() { return 0; }
 
1086
 
 
1087
  void Generate(MacroAssembler* masm);
 
1088
 
 
1089
  DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
 
1090
};
 
1091
 
955
1092
} }  // namespace v8::internal
956
1093
 
957
1094
#endif  // V8_CODE_STUBS_H_