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

« back to all changes in this revision

Viewing changes to src/ia32/macro-assembler-ia32.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:
29
29
#define V8_IA32_MACRO_ASSEMBLER_IA32_H_
30
30
 
31
31
#include "assembler.h"
 
32
#include "frames.h"
32
33
#include "v8globals.h"
33
34
 
34
35
namespace v8 {
50
51
// distinguish memory operands from other operands on ia32.
51
52
typedef Operand MemOperand;
52
53
 
 
54
enum RememberedSetAction { EMIT_REMEMBERED_SET, OMIT_REMEMBERED_SET };
 
55
enum SmiCheck { INLINE_SMI_CHECK, OMIT_SMI_CHECK };
 
56
 
 
57
 
 
58
bool AreAliased(Register r1, Register r2, Register r3, Register r4);
 
59
 
 
60
 
53
61
// MacroAssembler implements a collection of frequently used macros.
54
62
class MacroAssembler: public Assembler {
55
63
 public:
61
69
 
62
70
  // ---------------------------------------------------------------------------
63
71
  // GC Support
64
 
 
65
 
  // For page containing |object| mark region covering |addr| dirty.
66
 
  // RecordWriteHelper only works if the object is not in new
67
 
  // space.
68
 
  void RecordWriteHelper(Register object,
69
 
                         Register addr,
70
 
                         Register scratch);
71
 
 
72
 
  // Check if object is in new space.
73
 
  // scratch can be object itself, but it will be clobbered.
74
 
  void InNewSpace(Register object,
75
 
                  Register scratch,
76
 
                  Condition cc,  // equal for new space, not_equal otherwise.
77
 
                  Label* branch,
78
 
                  Label::Distance branch_near = Label::kFar);
79
 
 
80
 
  // For page containing |object| mark region covering [object+offset]
81
 
  // dirty. |object| is the object being stored into, |value| is the
82
 
  // object being stored. If offset is zero, then the scratch register
83
 
  // contains the array index into the elements array represented as a
84
 
  // Smi. All registers are clobbered by the operation. RecordWrite
 
72
  enum RememberedSetFinalAction {
 
73
    kReturnAtEnd,
 
74
    kFallThroughAtEnd
 
75
  };
 
76
 
 
77
  // Record in the remembered set the fact that we have a pointer to new space
 
78
  // at the address pointed to by the addr register.  Only works if addr is not
 
79
  // in new space.
 
80
  void RememberedSetHelper(Register object,  // Used for debug code.
 
81
                           Register addr,
 
82
                           Register scratch,
 
83
                           SaveFPRegsMode save_fp,
 
84
                           RememberedSetFinalAction and_then);
 
85
 
 
86
  void CheckPageFlag(Register object,
 
87
                     Register scratch,
 
88
                     int mask,
 
89
                     Condition cc,
 
90
                     Label* condition_met,
 
91
                     Label::Distance condition_met_distance = Label::kFar);
 
92
 
 
93
  // Check if object is in new space.  Jumps if the object is not in new space.
 
94
  // The register scratch can be object itself, but scratch will be clobbered.
 
95
  void JumpIfNotInNewSpace(Register object,
 
96
                           Register scratch,
 
97
                           Label* branch,
 
98
                           Label::Distance distance = Label::kFar) {
 
99
    InNewSpace(object, scratch, zero, branch, distance);
 
100
  }
 
101
 
 
102
  // Check if object is in new space.  Jumps if the object is in new space.
 
103
  // The register scratch can be object itself, but it will be clobbered.
 
104
  void JumpIfInNewSpace(Register object,
 
105
                        Register scratch,
 
106
                        Label* branch,
 
107
                        Label::Distance distance = Label::kFar) {
 
108
    InNewSpace(object, scratch, not_zero, branch, distance);
 
109
  }
 
110
 
 
111
  // Check if an object has a given incremental marking color.  Also uses ecx!
 
112
  void HasColor(Register object,
 
113
                Register scratch0,
 
114
                Register scratch1,
 
115
                Label* has_color,
 
116
                Label::Distance has_color_distance,
 
117
                int first_bit,
 
118
                int second_bit);
 
119
 
 
120
  void JumpIfBlack(Register object,
 
121
                   Register scratch0,
 
122
                   Register scratch1,
 
123
                   Label* on_black,
 
124
                   Label::Distance on_black_distance = Label::kFar);
 
125
 
 
126
  // Checks the color of an object.  If the object is already grey or black
 
127
  // then we just fall through, since it is already live.  If it is white and
 
128
  // we can determine that it doesn't need to be scanned, then we just mark it
 
129
  // black and fall through.  For the rest we jump to the label so the
 
130
  // incremental marker can fix its assumptions.
 
131
  void EnsureNotWhite(Register object,
 
132
                      Register scratch1,
 
133
                      Register scratch2,
 
134
                      Label* object_is_white_and_not_data,
 
135
                      Label::Distance distance);
 
136
 
 
137
  // Notify the garbage collector that we wrote a pointer into an object.
 
138
  // |object| is the object being stored into, |value| is the object being
 
139
  // stored.  value and scratch registers are clobbered by the operation.
 
140
  // The offset is the offset from the start of the object, not the offset from
 
141
  // the tagged HeapObject pointer.  For use with FieldOperand(reg, off).
 
142
  void RecordWriteField(
 
143
      Register object,
 
144
      int offset,
 
145
      Register value,
 
146
      Register scratch,
 
147
      SaveFPRegsMode save_fp,
 
148
      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
 
149
      SmiCheck smi_check = INLINE_SMI_CHECK);
 
150
 
 
151
  // As above, but the offset has the tag presubtracted.  For use with
 
152
  // Operand(reg, off).
 
153
  void RecordWriteContextSlot(
 
154
      Register context,
 
155
      int offset,
 
156
      Register value,
 
157
      Register scratch,
 
158
      SaveFPRegsMode save_fp,
 
159
      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
 
160
      SmiCheck smi_check = INLINE_SMI_CHECK) {
 
161
    RecordWriteField(context,
 
162
                     offset + kHeapObjectTag,
 
163
                     value,
 
164
                     scratch,
 
165
                     save_fp,
 
166
                     remembered_set_action,
 
167
                     smi_check);
 
168
  }
 
169
 
 
170
  // Notify the garbage collector that we wrote a pointer into a fixed array.
 
171
  // |array| is the array being stored into, |value| is the
 
172
  // object being stored.  |index| is the array index represented as a
 
173
  // Smi. All registers are clobbered by the operation RecordWriteArray
85
174
  // filters out smis so it does not update the write barrier if the
86
175
  // value is a smi.
87
 
  void RecordWrite(Register object,
88
 
                   int offset,
89
 
                   Register value,
90
 
                   Register scratch);
 
176
  void RecordWriteArray(
 
177
      Register array,
 
178
      Register value,
 
179
      Register index,
 
180
      SaveFPRegsMode save_fp,
 
181
      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
 
182
      SmiCheck smi_check = INLINE_SMI_CHECK);
91
183
 
92
184
  // For page containing |object| mark region covering |address|
93
185
  // dirty. |object| is the object being stored into, |value| is the
94
 
  // object being stored. All registers are clobbered by the
 
186
  // object being stored. The address and value registers are clobbered by the
95
187
  // operation. RecordWrite filters out smis so it does not update the
96
188
  // write barrier if the value is a smi.
97
 
  void RecordWrite(Register object,
98
 
                   Register address,
99
 
                   Register value);
 
189
  void RecordWrite(
 
190
      Register object,
 
191
      Register address,
 
192
      Register value,
 
193
      SaveFPRegsMode save_fp,
 
194
      RememberedSetAction remembered_set_action = EMIT_REMEMBERED_SET,
 
195
      SmiCheck smi_check = INLINE_SMI_CHECK);
100
196
 
101
197
#ifdef ENABLE_DEBUGGER_SUPPORT
102
198
  // ---------------------------------------------------------------------------
105
201
  void DebugBreak();
106
202
#endif
107
203
 
108
 
  // ---------------------------------------------------------------------------
109
 
  // Activation frames
110
 
 
111
 
  void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
112
 
  void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
113
 
 
114
 
  void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
115
 
  void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
116
 
 
117
204
  // Enter specific kind of exit frame. Expects the number of
118
205
  // arguments in register eax and sets up the number of arguments in
119
206
  // register edi and the pointer to the first argument in register
159
246
  void SetCallKind(Register dst, CallKind kind);
160
247
 
161
248
  // Invoke the JavaScript function code by either calling or jumping.
 
249
  void InvokeCode(Register code,
 
250
                  const ParameterCount& expected,
 
251
                  const ParameterCount& actual,
 
252
                  InvokeFlag flag,
 
253
                  const CallWrapper& call_wrapper,
 
254
                  CallKind call_kind) {
 
255
    InvokeCode(Operand(code), expected, actual, flag, call_wrapper, call_kind);
 
256
  }
 
257
 
162
258
  void InvokeCode(const Operand& code,
163
259
                  const ParameterCount& expected,
164
260
                  const ParameterCount& actual,
182
278
                      const CallWrapper& call_wrapper,
183
279
                      CallKind call_kind);
184
280
 
185
 
  void InvokeFunction(JSFunction* function,
 
281
  void InvokeFunction(Handle<JSFunction> function,
186
282
                      const ParameterCount& actual,
187
283
                      InvokeFlag flag,
188
284
                      const CallWrapper& call_wrapper,
225
321
                         Label* fail,
226
322
                         Label::Distance distance = Label::kFar);
227
323
 
 
324
  // Check if a map for a JSObject indicates that the object can have both smi
 
325
  // and HeapObject elements.  Jump to the specified label if it does not.
 
326
  void CheckFastObjectElements(Register map,
 
327
                               Label* fail,
 
328
                               Label::Distance distance = Label::kFar);
 
329
 
 
330
  // Check if a map for a JSObject indicates that the object has fast smi only
 
331
  // elements.  Jump to the specified label if it does not.
 
332
  void CheckFastSmiOnlyElements(Register map,
 
333
                                Label* fail,
 
334
                                Label::Distance distance = Label::kFar);
 
335
 
 
336
  // Check to see if maybe_number can be stored as a double in
 
337
  // FastDoubleElements. If it can, store it at the index specified by key in
 
338
  // the FastDoubleElements array elements, otherwise jump to fail.
 
339
  void StoreNumberToDoubleElements(Register maybe_number,
 
340
                                   Register elements,
 
341
                                   Register key,
 
342
                                   Register scratch1,
 
343
                                   XMMRegister scratch2,
 
344
                                   Label* fail,
 
345
                                   bool specialize_for_processor);
 
346
 
228
347
  // Check if the map of an object is equal to a specified map and branch to
229
348
  // label if not. Skip the smi check if not required (object is known to be a
230
349
  // heap object)
277
396
  void SmiTag(Register reg) {
278
397
    STATIC_ASSERT(kSmiTag == 0);
279
398
    STATIC_ASSERT(kSmiTagSize == 1);
280
 
    add(reg, Operand(reg));
 
399
    add(reg, reg);
281
400
  }
282
401
  void SmiUntag(Register reg) {
283
402
    sar(reg, kSmiTagSize);
332
451
  // ---------------------------------------------------------------------------
333
452
  // Exception handling
334
453
 
335
 
  // Push a new try handler and link into try handler chain.  The return
336
 
  // address must be pushed before calling this helper.
337
 
  void PushTryHandler(CodeLocation try_location, HandlerType type);
 
454
  // Push a new try handler and link it into try handler chain.
 
455
  void PushTryHandler(CodeLocation try_location,
 
456
                      HandlerType type,
 
457
                      int handler_index);
338
458
 
339
459
  // Unlink the stack handler on top of the stack from the try handler chain.
340
460
  void PopTryHandler();
465
585
                 Register length,
466
586
                 Register scratch);
467
587
 
 
588
  // Initialize fields with filler values.  Fields starting at |start_offset|
 
589
  // not including end_offset are overwritten with the value in |filler|.  At
 
590
  // the end the loop, |start_offset| takes the value of |end_offset|.
 
591
  void InitializeFieldsWithFiller(Register start_offset,
 
592
                                  Register end_offset,
 
593
                                  Register filler);
 
594
 
468
595
  // ---------------------------------------------------------------------------
469
596
  // Support functions.
470
597
 
 
598
  // Check a boolean-bit of a Smi field.
 
599
  void BooleanBitTest(Register object, int field_offset, int bit_index);
 
600
 
471
601
  // Check if result is zero and op is negative.
472
602
  void NegativeZeroTest(Register result, Register op, Label* then_label);
473
603
 
484
614
  void TryGetFunctionPrototype(Register function,
485
615
                               Register result,
486
616
                               Register scratch,
487
 
                               Label* miss);
 
617
                               Label* miss,
 
618
                               bool miss_on_bound_function = false);
488
619
 
489
620
  // Generates code for reporting that an illegal operation has
490
621
  // occurred.
502
633
  // Call a code stub.  Generate the code if necessary.
503
634
  void CallStub(CodeStub* stub, unsigned ast_id = kNoASTId);
504
635
 
505
 
  // Call a code stub and return the code object called.  Try to generate
506
 
  // the code if necessary.  Do not perform a GC but instead return a retry
507
 
  // after GC failure.
508
 
  MUST_USE_RESULT MaybeObject* TryCallStub(CodeStub* stub);
509
 
 
510
636
  // Tail call a code stub (jump).  Generate the code if necessary.
511
637
  void TailCallStub(CodeStub* stub);
512
638
 
513
 
  // Tail call a code stub (jump) and return the code object called.  Try to
514
 
  // generate the code if necessary.  Do not perform a GC but instead return
515
 
  // a retry after GC failure.
516
 
  MUST_USE_RESULT MaybeObject* TryTailCallStub(CodeStub* stub);
517
 
 
518
639
  // Return from a code stub after popping its arguments.
519
640
  void StubReturn(int argc);
520
641
 
522
643
  void CallRuntime(const Runtime::Function* f, int num_arguments);
523
644
  void CallRuntimeSaveDoubles(Runtime::FunctionId id);
524
645
 
525
 
  // Call a runtime function, returning the CodeStub object called.
526
 
  // Try to generate the stub code if necessary.  Do not perform a GC
527
 
  // but instead return a retry after GC failure.
528
 
  MUST_USE_RESULT MaybeObject* TryCallRuntime(const Runtime::Function* f,
529
 
                                              int num_arguments);
530
 
 
531
646
  // Convenience function: Same as above, but takes the fid instead.
532
647
  void CallRuntime(Runtime::FunctionId id, int num_arguments);
533
648
 
534
 
  // Convenience function: Same as above, but takes the fid instead.
535
 
  MUST_USE_RESULT MaybeObject* TryCallRuntime(Runtime::FunctionId id,
536
 
                                              int num_arguments);
537
 
 
538
649
  // Convenience function: call an external reference.
539
650
  void CallExternalReference(ExternalReference ref, int num_arguments);
540
651
 
545
656
                                 int num_arguments,
546
657
                                 int result_size);
547
658
 
548
 
  // Tail call of a runtime routine (jump). Try to generate the code if
549
 
  // necessary. Do not perform a GC but instead return a retry after GC failure.
550
 
  MUST_USE_RESULT MaybeObject* TryTailCallExternalReference(
551
 
      const ExternalReference& ext, int num_arguments, int result_size);
552
 
 
553
659
  // Convenience function: tail call a runtime routine (jump).
554
660
  void TailCallRuntime(Runtime::FunctionId fid,
555
661
                       int num_arguments,
556
662
                       int result_size);
557
663
 
558
 
  // Convenience function: tail call a runtime routine (jump). Try to generate
559
 
  // the code if necessary. Do not perform a GC but instead return a retry after
560
 
  // GC failure.
561
 
  MUST_USE_RESULT MaybeObject* TryTailCallRuntime(Runtime::FunctionId fid,
562
 
                                                  int num_arguments,
563
 
                                                  int result_size);
564
 
 
565
664
  // Before calling a C-function from generated code, align arguments on stack.
566
665
  // After aligning the frame, arguments must be stored in esp[0], esp[4],
567
666
  // etc., not pushed. The argument count assumes all arguments are word sized.
586
685
  // stores the pointer to the reserved slot into esi.
587
686
  void PrepareCallApiFunction(int argc);
588
687
 
589
 
  // Calls an API function. Allocates HandleScope, extracts
590
 
  // returned value from handle and propagates exceptions.
591
 
  // Clobbers ebx, edi and caller-save registers. Restores context.
592
 
  // On return removes stack_space * kPointerSize (GCed).
593
 
  MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function,
594
 
                                           int stack_space);
 
688
  // Calls an API function.  Allocates HandleScope, extracts returned value
 
689
  // from handle and propagates exceptions.  Clobbers ebx, edi and
 
690
  // caller-save registers.  Restores context.  On return removes
 
691
  // stack_space * kPointerSize (GCed).
 
692
  void CallApiFunctionAndReturn(Address function_address, int stack_space);
595
693
 
596
694
  // Jump to a runtime routine.
597
695
  void JumpToExternalReference(const ExternalReference& ext);
598
696
 
599
 
  MaybeObject* TryJumpToExternalReference(const ExternalReference& ext);
600
 
 
601
 
 
602
697
  // ---------------------------------------------------------------------------
603
698
  // Utilities
604
699
 
667
762
  bool generating_stub() { return generating_stub_; }
668
763
  void set_allow_stub_calls(bool value) { allow_stub_calls_ = value; }
669
764
  bool allow_stub_calls() { return allow_stub_calls_; }
 
765
  void set_has_frame(bool value) { has_frame_ = value; }
 
766
  bool has_frame() { return has_frame_; }
 
767
  inline bool AllowThisStubCall(CodeStub* stub);
670
768
 
671
769
  // ---------------------------------------------------------------------------
672
770
  // String utilities.
690
788
    return SafepointRegisterStackIndex(reg.code());
691
789
  }
692
790
 
 
791
  // Activation support.
 
792
  void EnterFrame(StackFrame::Type type);
 
793
  void LeaveFrame(StackFrame::Type type);
 
794
 
693
795
 private:
694
796
  bool generating_stub_;
695
797
  bool allow_stub_calls_;
 
798
  bool has_frame_;
696
799
  // This handle will be patched with the code object on installation.
697
800
  Handle<Object> code_object_;
698
801
 
703
806
                      const Operand& code_operand,
704
807
                      Label* done,
705
808
                      InvokeFlag flag,
706
 
                      Label::Distance done_near = Label::kFar,
 
809
                      Label::Distance done_distance,
707
810
                      const CallWrapper& call_wrapper = NullCallWrapper(),
708
811
                      CallKind call_kind = CALL_AS_METHOD);
709
812
 
710
 
  // Activation support.
711
 
  void EnterFrame(StackFrame::Type type);
712
 
  void LeaveFrame(StackFrame::Type type);
713
 
 
714
813
  void EnterExitFramePrologue();
715
814
  void EnterExitFrameEpilogue(int argc, bool save_doubles);
716
815
 
729
828
                                                    Register scratch,
730
829
                                                    bool gc_allowed);
731
830
 
 
831
  // Helper for implementing JumpIfNotInNewSpace and JumpIfInNewSpace.
 
832
  void InNewSpace(Register object,
 
833
                  Register scratch,
 
834
                  Condition cc,
 
835
                  Label* condition_met,
 
836
                  Label::Distance condition_met_distance = Label::kFar);
 
837
 
 
838
  // Helper for finding the mark bits for an address.  Afterwards, the
 
839
  // bitmap register points at the word with the mark bits and the mask
 
840
  // the position of the first bit.  Uses ecx as scratch and leaves addr_reg
 
841
  // unchanged.
 
842
  inline void GetMarkBits(Register addr_reg,
 
843
                          Register bitmap_reg,
 
844
                          Register mask_reg);
 
845
 
 
846
  // Helper for throwing exceptions.  Compute a handler address and jump to
 
847
  // it.  See the implementation for register usage.
 
848
  void JumpToHandlerEntry();
732
849
 
733
850
  // Compute memory operands for safepoint stack slots.
734
851
  Operand SafepointRegisterSlot(Register reg);
764
881
// Static helper functions.
765
882
 
766
883
// Generate an Operand for loading a field from an object.
767
 
static inline Operand FieldOperand(Register object, int offset) {
 
884
inline Operand FieldOperand(Register object, int offset) {
768
885
  return Operand(object, offset - kHeapObjectTag);
769
886
}
770
887
 
771
888
 
772
889
// Generate an Operand for loading an indexed field from an object.
773
 
static inline Operand FieldOperand(Register object,
774
 
                                   Register index,
775
 
                                   ScaleFactor scale,
776
 
                                   int offset) {
 
890
inline Operand FieldOperand(Register object,
 
891
                            Register index,
 
892
                            ScaleFactor scale,
 
893
                            int offset) {
777
894
  return Operand(object, index, scale, offset - kHeapObjectTag);
778
895
}
779
896
 
780
897
 
781
 
static inline Operand ContextOperand(Register context, int index) {
 
898
inline Operand ContextOperand(Register context, int index) {
782
899
  return Operand(context, Context::SlotOffset(index));
783
900
}
784
901
 
785
902
 
786
 
static inline Operand GlobalObjectOperand() {
 
903
inline Operand GlobalObjectOperand() {
787
904
  return ContextOperand(esi, Context::GLOBAL_INDEX);
788
905
}
789
906