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

Side by Side Diff: src/macro-assembler-ia32.h

Issue 9328: Initial (stub) port of jump targets to the ARM platform.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 12 years, 1 month 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
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 IN_C_ENTRY 45 IN_C_ENTRY
46 }; 46 };
47 47
48 enum HandlerType { 48 enum HandlerType {
49 TRY_CATCH_HANDLER, 49 TRY_CATCH_HANDLER,
50 TRY_FINALLY_HANDLER, 50 TRY_FINALLY_HANDLER,
51 JS_ENTRY_HANDLER 51 JS_ENTRY_HANDLER
52 }; 52 };
53 53
54 54
55 // -------------------------------------------------------------------------
56 // Virtual frames
57 //
58 // The virtual frame is an abstraction of the physical stack frame. It
59 // encapsulates the parameters, frame-allocated locals, and the expression
60 // stack. It supports push/pop operations on the expression stack, as well
61 // as random access to the expression stack elements, locals, and
62 // parameters.
63
64 class VirtualFrame : public Malloced {
65 public:
66 // Construct a virtual frame with the given code generator used to
67 // generate code.
68 explicit VirtualFrame(CodeGenerator* cgen);
69
70 // Construct a virtual frame that is a clone of an existing one, initially
71 // with an identical state.
72 explicit VirtualFrame(VirtualFrame* original);
73
74 // The height of the virtual expression stack. Always non-negative.
75 int height() const { return height_; }
76
77 // Forget elements from the top of the expression stack. This is
78 // used when the stack pointer is manually lowered to pop values
79 // left by statements (eg, for...in, try...finally) that have been
80 // escaped from.
81 void Forget(int count);
82
83 // Make this virtual frame have a state identical to an expected virtual
84 // frame. As a side effect, code may be emitted to make this frame match
85 // the expected one.
86 void MergeTo(VirtualFrame* expected);
87
88 // Emit code for the physical JS entry and exit frame sequences. After
89 // calling Enter, the virtual frame is ready for use; and after calling
90 // Exit it should not be used. Note that Enter does not allocate space in
91 // the physical frame for storing frame-allocated locals.
92 void Enter();
93 void Exit();
94
95 // Allocate and initialize the frame-allocated locals. The number of
96 // locals is known from the frame's code generator's state (specifically
97 // its scope). As a side effect, code may be emitted.
98 void AllocateLocals();
99
100 // The current top of the expression stack as an assembly operand.
101 Operand Top() const { return Operand(esp, 0); }
102
103 // An element of the expression stack as an assembly operand.
104 Operand Element(int index) const {
105 return Operand(esp, index * kPointerSize);
106 }
107
108 // A frame-allocated local as an assembly operand.
109 Operand Local(int index) const {
110 ASSERT(0 <= index && index < frame_local_count_);
111 return Operand(ebp, kLocal0Offset - index * kPointerSize);
112 }
113
114 // The function frame slot.
115 Operand Function() const { return Operand(ebp, kFunctionOffset); }
116
117 // The context frame slot.
118 Operand Context() const { return Operand(ebp, kContextOffset); }
119
120 // A parameter as an assembly operand.
121 Operand Parameter(int index) const {
122 ASSERT(-1 <= index && index < parameter_count_);
123 return Operand(ebp, (1 + parameter_count_ - index) * kPointerSize);
124 }
125
126 // The receiver frame slot.
127 Operand Receiver() const { return Parameter(-1); }
128
129 // Push a try-catch or try-finally handler on top of the virtual frame.
130 inline void PushTryHandler(HandlerType type);
131
132 // Call a code stub, given the number of arguments it expects on (and
133 // removes from) the top of the physical frame.
134 inline void CallStub(CodeStub* stub, int frame_arg_count);
135
136 // Call the runtime, given the number of arguments expected on (and
137 // removed from) the top of the physical frame.
138 inline void CallRuntime(Runtime::Function* f, int frame_arg_count);
139 inline void CallRuntime(Runtime::FunctionId id, int frame_arg_count);
140
141 // Invoke a builtin, given the number of arguments it expects on (and
142 // removes from) the top of the physical frame.
143 inline void InvokeBuiltin(Builtins::JavaScript id,
144 InvokeFlag flag,
145 int frame_arg_count);
146
147 // Call into a JS code object, given the number of arguments it expects on
148 // (and removes from) the top of the physical frame.
149 inline void CallCode(Handle<Code> ic,
150 RelocInfo::Mode rmode,
151 int frame_arg_count);
152
153 // Drop a number of elements from the top of the expression stack. May
154 // emit code to effect the physical frame.
155 inline void Drop(int count);
156
157 // Pop and discard an element from the top of the expression stack.
158 // Specifically does not clobber any registers excepting possibly the
159 // stack pointer.
160 inline void Pop();
161
162 // Pop and save an element from the top of the expression stack. May emit
163 // code.
164 inline void Pop(Register reg);
165 inline void Pop(Operand operand);
166
167 // Push an element on top of the expression stack. May emit code.
168 inline void Push(Register reg);
169 inline void Push(Operand operand);
170 inline void Push(Immediate immediate);
171
172 private:
173 static const int kLocal0Offset = JavaScriptFrameConstants::kLocal0Offset;
174 static const int kFunctionOffset = JavaScriptFrameConstants::kFunctionOffset;
175 static const int kContextOffset = StandardFrameConstants::kContextOffset;
176
177 static const int kHandlerSize = StackHandlerConstants::kSize / kPointerSize;
178
179 MacroAssembler* masm_;
180
181 // The number of frame-allocated locals and parameters respectively.
182 int frame_local_count_;
183 int parameter_count_;
184
185 // The height of the expression stack.
186 int height_;
187
188 // The JumpTarget class explicitly sets the height_ field of the expected
189 // frame at the actual return target.
190 friend class JumpTarget;
191 };
192
193
194 // -------------------------------------------------------------------------
195 // Jump targets
196 //
197 // A jump target is an abstraction of a control-flow target in generated
198 // code. It encapsulates an assembler label and an expected virtual frame
199 // layout at that label. The first time control flow reaches the target,
200 // either via jumping or branching or by binding the target, the expected
201 // frame is set. If control flow subsequently reaches the target, code may
202 // be emitted to ensure that the current frame matches the expected frame.
203 //
204 // A jump target must have been reached via control flow (either by jumping,
205 // branching, or falling through) when it is bound. In particular, this
206 // means that at least one of the control-flow graph edges reaching the
207 // target must be a forward edge and must be compiled before any backward
208 // edges.
209
210 class JumpTarget : public ZoneObject { // Shadows are dynamically allocated.
211 public:
212 // Construct a jump target with a given code generator used to generate
213 // code and to provide access to a current frame.
214 explicit JumpTarget(CodeGenerator* cgen);
215
216 // Construct a jump target without a code generator. A code generator
217 // must be supplied before using the jump target as a label. This is
218 // useful, eg, when jump targets are embedded in AST nodes.
219 JumpTarget();
220
221 virtual ~JumpTarget() { delete expected_frame_; }
222
223 // Supply a code generator. This function expects to be given a non-null
224 // code generator, and to be called only when the code generator is not
225 // yet set.
226 void set_code_generator(CodeGenerator* cgen);
227
228 // Accessors.
229 CodeGenerator* code_generator() const { return code_generator_; }
230
231 MacroAssembler* masm() const { return masm_; }
232
233 Label* label() { return &label_; }
234
235 VirtualFrame* expected_frame() const { return expected_frame_; }
236 void set_expected_frame(VirtualFrame* frame) {
237 expected_frame_ = frame;
238 }
239
240 // Predicates testing the state of the encapsulated label.
241 bool is_bound() const { return label_.is_bound(); }
242 bool is_linked() const { return label_.is_linked(); }
243 bool is_unused() const { return label_.is_unused(); }
244
245 // Treat the jump target as a fresh one---the label is unused and the
246 // expected frame if any is reset.
247 void Unuse() {
248 label_.Unuse();
249 delete expected_frame_;
250 expected_frame_ = NULL;
251 }
252
253 // True if this jump target is the (non-shadowed) target of the return
254 // from the code generator's current function.
255 bool IsActualFunctionReturn();
256
257 // Emit a jump to the target. If there is no expected frame, the code
258 // generator's current frame becomes the expected one. If there is
259 // already an expected frame, code may be emitted to merge the current
260 // frame to the expected one. After the jump, the code generate has no
261 // current frame (because control flow does not fall through from a jump).
262 // A new current frame can be picked up by, eg, binding a jump target with
263 // an expected frame.
264 void Jump();
265
266 // Emit a conditional branch to the target. If there is no expected
267 // frame, a clone of the code generator's current frame becomes the
268 // expected one. If there is already an expected frame, code may be
269 // emitted to merge the current frame to the expected one.
270 void Branch(Condition cc, Hint hint = no_hint);
271
272 // Bind a jump target. If there is no expected frame and there is a
273 // current frame (ie, control flow is falling through to the target), then
274 // a clone of the current frame becomes the expected one. If there is a
275 // current frame and an expected one (eg, control flow is falling through
276 // to a target that has already been reached via a jump or branch), then
277 // code may be emitted to merge the frames. A jump target that already
278 // has an expected frame can be bound even if there is no current
279 // frame---in that case, the new current frame is picked up from the jump
280 // target.
281 void Bind();
282
283 // Call a jump target. A clone of the current frame, with a return
284 // address pushed on top of it, becomes the expected frame at the target.
285 // The current frame after the site of the call (ie, after the return) is
286 // expected to be the same as before the call. This operation is only
287 // supported when there is a current frame and when there is no expected
288 // frame at the label.
289 void Call();
290
291 protected:
292 // The encapsulated assembler label.
293 Label label_;
294
295 // The expected frame where the label is bound, or NULL.
296 VirtualFrame* expected_frame_;
297
298 private:
299 // The code generator gives access to the current frame.
300 CodeGenerator* code_generator_;
301
302 // Used to emit code.
303 MacroAssembler* masm_;
304 };
305
306
307 // -------------------------------------------------------------------------
308 // Shadow jump targets
309 //
310 // Shadow jump targets represent a jump target that is temporarily shadowed
311 // by another one (represented by the original during shadowing). They are
312 // used to catch jumps to labels in certain contexts, e.g. try blocks.
313 // After shadowing ends, the formerly shadowed target is again represented
314 // by the original and the ShadowTarget can be used as a jump target in its
315 // own right, representing the formerly shadowing target.
316
317 class ShadowTarget : public JumpTarget {
318 public:
319 // Construct a shadow a jump target. After construction, the original
320 // jump target shadows the former target, which is hidden as the
321 // newly-constructed shadow target.
322 explicit ShadowTarget(JumpTarget* original);
323
324 virtual ~ShadowTarget() {
325 ASSERT(!is_shadowing_);
326 }
327
328 // End shadowing. After shadowing ends, the original jump target gives
329 // access to the formerly shadowed target and the shadow target object
330 // gives access to the formerly shadowing target.
331 void StopShadowing();
332
333 // During shadowing, the currently shadowing target. After shadowing, the
334 // target that was shadowed.
335 JumpTarget* original_target() const { return original_target_; }
336
337 private:
338 // During shadowing, the currently shadowing target. After shadowing, the
339 // target that was shadowed.
340 JumpTarget* original_target_;
341
342 // During shadowing, the saved state of the shadowed target's label.
343 int original_pos_;
344
345 // During shadowing, the saved state of the shadowed target's expected
346 // frame.
347 VirtualFrame* original_expected_frame_;
348
349 #ifdef DEBUG
350 bool is_shadowing_;
351 #endif
352 };
353
354
355 // MacroAssembler implements a collection of frequently used macros. 55 // MacroAssembler implements a collection of frequently used macros.
356 class MacroAssembler: public Assembler { 56 class MacroAssembler: public Assembler {
357 public: 57 public:
358 MacroAssembler(void* buffer, int size); 58 MacroAssembler(void* buffer, int size);
359 59
360 // --------------------------------------------------------------------------- 60 // ---------------------------------------------------------------------------
361 // GC Support 61 // GC Support
362 62
363 // Set the remembered set bit for [object+offset]. 63 // Set the remembered set bit for [object+offset].
364 // object is the object being stored into, value is the object being stored. 64 // object is the object being stored into, value is the object being stored.
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 315
616 316
617 // Generate an Operand for loading an indexed field from an object. 317 // Generate an Operand for loading an indexed field from an object.
618 static inline Operand FieldOperand(Register object, 318 static inline Operand FieldOperand(Register object,
619 Register index, 319 Register index,
620 ScaleFactor scale, 320 ScaleFactor scale,
621 int offset) { 321 int offset) {
622 return Operand(object, index, scale, offset - kHeapObjectTag); 322 return Operand(object, index, scale, offset - kHeapObjectTag);
623 } 323 }
624 324
625
626 // -------------------------------------------------------------------------
627 // VirtualFrame inline functions.
628
629 #define __ masm_->
630
631 void VirtualFrame::PushTryHandler(HandlerType type) {
632 // Grow the expression stack by handler size less two (the return address
633 // is already pushed by a call instruction, and PushTryHandler from the
634 // macro assembler will leave the top of stack in the eax register to be
635 // pushed separately).
636 height_ += (kHandlerSize - 2);
637 __ PushTryHandler(IN_JAVASCRIPT, type);
638 // TODO(1222589): remove the reliance of PushTryHandler on a cached TOS
639 Push(eax);
640 }
641
642
643 void VirtualFrame::CallStub(CodeStub* stub, int frame_arg_count) {
644 ASSERT(frame_arg_count >= 0);
645 ASSERT(height_ >= frame_arg_count);
646 height_ -= frame_arg_count;
647 __ CallStub(stub);
648 }
649
650
651 void VirtualFrame::CallRuntime(Runtime::Function* f, int frame_arg_count) {
652 ASSERT(frame_arg_count >= 0);
653 ASSERT(height_ >= frame_arg_count);
654 height_ -= frame_arg_count;
655 __ CallRuntime(f, frame_arg_count);
656 }
657
658
659 void VirtualFrame::CallRuntime(Runtime::FunctionId id, int frame_arg_count) {
660 ASSERT(frame_arg_count >= 0);
661 ASSERT(height_ >= frame_arg_count);
662 height_ -= frame_arg_count;
663 __ CallRuntime(id, frame_arg_count);
664 }
665
666
667 void VirtualFrame::InvokeBuiltin(Builtins::JavaScript id,
668 InvokeFlag flag,
669 int frame_arg_count) {
670 ASSERT(frame_arg_count >= 0);
671 ASSERT(height_ >= frame_arg_count);
672 height_ -= frame_arg_count;
673 __ InvokeBuiltin(id, flag);
674 }
675
676
677 void VirtualFrame::CallCode(Handle<Code> code,
678 RelocInfo::Mode rmode,
679 int frame_arg_count) {
680 ASSERT(frame_arg_count >= 0);
681 ASSERT(height_ >= frame_arg_count);
682 height_ -= frame_arg_count;
683 __ call(code, rmode);
684 }
685
686
687 void VirtualFrame::Drop(int count) {
688 ASSERT(count >= 0);
689 ASSERT(height_ >= count);
690 if (count > 0) {
691 __ add(Operand(esp), Immediate(count * kPointerSize));
692 height_ -= count;
693 }
694 }
695
696
697 void VirtualFrame::Pop() {
698 ASSERT(height_ > 0);
699 __ add(Operand(esp), Immediate(kPointerSize));
700 height_--;
701 }
702
703
704 void VirtualFrame::Pop(Register reg) {
705 ASSERT(height_ > 0);
706 __ pop(reg);
707 height_--;
708 }
709
710
711 void VirtualFrame::Pop(Operand operand) {
712 ASSERT(height_ > 0);
713 __ pop(operand);
714 height_--;
715 }
716
717
718 void VirtualFrame::Push(Register reg) {
719 height_++;
720 __ push(reg);
721 }
722
723
724 void VirtualFrame::Push(Operand operand) {
725 height_++;
726 __ push(operand);
727 }
728
729
730 void VirtualFrame::Push(Immediate immediate) {
731 height_++;
732 __ push(immediate);
733 }
734
735 #undef __
736
737 } } // namespace v8::internal 325 } } // namespace v8::internal
738 326
739 #endif // V8_MACRO_ASSEMBLER_IA32_H_ 327 #endif // V8_MACRO_ASSEMBLER_IA32_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698