OLD | NEW |
| (Empty) |
1 // Copyright 2008 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 #include "v8.h" | |
29 | |
30 #if defined(V8_TARGET_ARCH_ARM) | |
31 | |
32 #include "codegen-inl.h" | |
33 #include "jump-target-inl.h" | |
34 #include "register-allocator-inl.h" | |
35 #include "virtual-frame-inl.h" | |
36 | |
37 namespace v8 { | |
38 namespace internal { | |
39 | |
40 // ------------------------------------------------------------------------- | |
41 // JumpTarget implementation. | |
42 | |
43 #define __ ACCESS_MASM(cgen()->masm()) | |
44 | |
45 void JumpTarget::DoJump() { | |
46 ASSERT(cgen()->has_valid_frame()); | |
47 // Live non-frame registers are not allowed at unconditional jumps | |
48 // because we have no way of invalidating the corresponding results | |
49 // which are still live in the C++ code. | |
50 ASSERT(cgen()->HasValidEntryRegisters()); | |
51 | |
52 if (entry_frame_set_) { | |
53 if (entry_label_.is_bound()) { | |
54 // If we already bound and generated code at the destination then it | |
55 // is too late to ask for less optimistic type assumptions. | |
56 ASSERT(entry_frame_.IsCompatibleWith(cgen()->frame())); | |
57 } | |
58 // There already a frame expectation at the target. | |
59 cgen()->frame()->MergeTo(&entry_frame_); | |
60 cgen()->DeleteFrame(); | |
61 } else { | |
62 // Clone the current frame to use as the expected one at the target. | |
63 set_entry_frame(cgen()->frame()); | |
64 // Zap the fall-through frame since the jump was unconditional. | |
65 RegisterFile empty; | |
66 cgen()->SetFrame(NULL, &empty); | |
67 } | |
68 if (entry_label_.is_bound()) { | |
69 // You can't jump backwards to an already bound label unless you admitted | |
70 // up front that this was a bidirectional jump target. Bidirectional jump | |
71 // targets will zap their type info when bound in case some later virtual | |
72 // frame with less precise type info branches to them. | |
73 ASSERT(direction_ != FORWARD_ONLY); | |
74 } | |
75 __ jmp(&entry_label_); | |
76 } | |
77 | |
78 | |
79 void JumpTarget::DoBranch(Condition cond, Hint ignored) { | |
80 ASSERT(cgen()->has_valid_frame()); | |
81 | |
82 if (entry_frame_set_) { | |
83 if (entry_label_.is_bound()) { | |
84 // If we already bound and generated code at the destination then it | |
85 // is too late to ask for less optimistic type assumptions. | |
86 ASSERT(entry_frame_.IsCompatibleWith(cgen()->frame())); | |
87 } | |
88 // We have an expected frame to merge to on the backward edge. | |
89 cgen()->frame()->MergeTo(&entry_frame_, cond); | |
90 } else { | |
91 // Clone the current frame to use as the expected one at the target. | |
92 set_entry_frame(cgen()->frame()); | |
93 } | |
94 if (entry_label_.is_bound()) { | |
95 // You can't branch backwards to an already bound label unless you admitted | |
96 // up front that this was a bidirectional jump target. Bidirectional jump | |
97 // targets will zap their type info when bound in case some later virtual | |
98 // frame with less precise type info branches to them. | |
99 ASSERT(direction_ != FORWARD_ONLY); | |
100 } | |
101 __ b(cond, &entry_label_); | |
102 if (cond == al) { | |
103 cgen()->DeleteFrame(); | |
104 } | |
105 } | |
106 | |
107 | |
108 void JumpTarget::Call() { | |
109 // Call is used to push the address of the catch block on the stack as | |
110 // a return address when compiling try/catch and try/finally. We | |
111 // fully spill the frame before making the call. The expected frame | |
112 // at the label (which should be the only one) is the spilled current | |
113 // frame plus an in-memory return address. The "fall-through" frame | |
114 // at the return site is the spilled current frame. | |
115 ASSERT(cgen()->has_valid_frame()); | |
116 // There are no non-frame references across the call. | |
117 ASSERT(cgen()->HasValidEntryRegisters()); | |
118 ASSERT(!is_linked()); | |
119 | |
120 // Calls are always 'forward' so we use a copy of the current frame (plus | |
121 // one for a return address) as the expected frame. | |
122 ASSERT(!entry_frame_set_); | |
123 VirtualFrame target_frame = *cgen()->frame(); | |
124 target_frame.Adjust(1); | |
125 set_entry_frame(&target_frame); | |
126 | |
127 __ bl(&entry_label_); | |
128 } | |
129 | |
130 | |
131 void JumpTarget::DoBind() { | |
132 ASSERT(!is_bound()); | |
133 | |
134 // Live non-frame registers are not allowed at the start of a basic | |
135 // block. | |
136 ASSERT(!cgen()->has_valid_frame() || cgen()->HasValidEntryRegisters()); | |
137 | |
138 if (cgen()->has_valid_frame()) { | |
139 if (direction_ != FORWARD_ONLY) cgen()->frame()->ForgetTypeInfo(); | |
140 // If there is a current frame we can use it on the fall through. | |
141 if (!entry_frame_set_) { | |
142 entry_frame_ = *cgen()->frame(); | |
143 entry_frame_set_ = true; | |
144 } else { | |
145 cgen()->frame()->MergeTo(&entry_frame_); | |
146 // On fall through we may have to merge both ways. | |
147 if (direction_ != FORWARD_ONLY) { | |
148 // This will not need to adjust the virtual frame entries that are | |
149 // register allocated since that was done above and they now match. | |
150 // But it does need to adjust the entry_frame_ of this jump target | |
151 // to make it potentially less optimistic. Later code can branch back | |
152 // to this jump target and we need to assert that that code does not | |
153 // have weaker assumptions about types. | |
154 entry_frame_.MergeTo(cgen()->frame()); | |
155 } | |
156 } | |
157 } else { | |
158 // If there is no current frame we must have an entry frame which we can | |
159 // copy. | |
160 ASSERT(entry_frame_set_); | |
161 RegisterFile empty; | |
162 cgen()->SetFrame(new VirtualFrame(&entry_frame_), &empty); | |
163 } | |
164 | |
165 __ bind(&entry_label_); | |
166 } | |
167 | |
168 | |
169 #undef __ | |
170 | |
171 | |
172 } } // namespace v8::internal | |
173 | |
174 #endif // V8_TARGET_ARCH_ARM | |
OLD | NEW |