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

Side by Side Diff: src/jump-target.cc

Issue 1164002: Split the virtual frame into heavy and light versions.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 months 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
« no previous file with comments | « src/ia32/virtual-frame-ia32.h ('k') | src/jump-target-heavy.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 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 30 matching lines...) Expand all
41 41
42 42
43 void JumpTarget::Unuse() { 43 void JumpTarget::Unuse() {
44 reaching_frames_.Clear(); 44 reaching_frames_.Clear();
45 merge_labels_.Clear(); 45 merge_labels_.Clear();
46 entry_frame_ = NULL; 46 entry_frame_ = NULL;
47 entry_label_.Unuse(); 47 entry_label_.Unuse();
48 } 48 }
49 49
50 50
51 void JumpTarget::ComputeEntryFrame() {
52 // Given: a collection of frames reaching by forward CFG edges and
53 // the directionality of the block. Compute: an entry frame for the
54 // block.
55
56 Counters::compute_entry_frame.Increment();
57 #ifdef DEBUG
58 if (compiling_deferred_code_) {
59 ASSERT(reaching_frames_.length() > 1);
60 VirtualFrame* frame = reaching_frames_[0];
61 bool all_identical = true;
62 for (int i = 1; i < reaching_frames_.length(); i++) {
63 if (!frame->Equals(reaching_frames_[i])) {
64 all_identical = false;
65 break;
66 }
67 }
68 ASSERT(!all_identical || all_identical);
69 }
70 #endif
71
72 // Choose an initial frame.
73 VirtualFrame* initial_frame = reaching_frames_[0];
74
75 // A list of pointers to frame elements in the entry frame. NULL
76 // indicates that the element has not yet been determined.
77 int length = initial_frame->element_count();
78 ZoneList<FrameElement*> elements(length);
79
80 // Initially populate the list of elements based on the initial
81 // frame.
82 for (int i = 0; i < length; i++) {
83 FrameElement element = initial_frame->elements_[i];
84 // We do not allow copies or constants in bidirectional frames.
85 if (direction_ == BIDIRECTIONAL) {
86 if (element.is_constant() || element.is_copy()) {
87 elements.Add(NULL);
88 continue;
89 }
90 }
91 elements.Add(&initial_frame->elements_[i]);
92 }
93
94 // Compute elements based on the other reaching frames.
95 if (reaching_frames_.length() > 1) {
96 for (int i = 0; i < length; i++) {
97 FrameElement* element = elements[i];
98 for (int j = 1; j < reaching_frames_.length(); j++) {
99 // Element computation is monotonic: new information will not
100 // change our decision about undetermined or invalid elements.
101 if (element == NULL || !element->is_valid()) break;
102
103 FrameElement* other = &reaching_frames_[j]->elements_[i];
104 element = element->Combine(other);
105 if (element != NULL && !element->is_copy()) {
106 ASSERT(other != NULL);
107 // We overwrite the number information of one of the incoming frames.
108 // This is safe because we only use the frame for emitting merge code.
109 // The number information of incoming frames is not used anymore.
110 element->set_number_info(NumberInfo::Combine(element->number_info(),
111 other->number_info()));
112 }
113 }
114 elements[i] = element;
115 }
116 }
117
118 // Build the new frame. A freshly allocated frame has memory elements
119 // for the parameters and some platform-dependent elements (e.g.,
120 // return address). Replace those first.
121 entry_frame_ = new VirtualFrame();
122 int index = 0;
123 for (; index < entry_frame_->element_count(); index++) {
124 FrameElement* target = elements[index];
125 // If the element is determined, set it now. Count registers. Mark
126 // elements as copied exactly when they have a copy. Undetermined
127 // elements are initially recorded as if in memory.
128 if (target != NULL) {
129 entry_frame_->elements_[index] = *target;
130 InitializeEntryElement(index, target);
131 }
132 }
133 // Then fill in the rest of the frame with new elements.
134 for (; index < length; index++) {
135 FrameElement* target = elements[index];
136 if (target == NULL) {
137 entry_frame_->elements_.Add(
138 FrameElement::MemoryElement(NumberInfo::Uninitialized()));
139 } else {
140 entry_frame_->elements_.Add(*target);
141 InitializeEntryElement(index, target);
142 }
143 }
144
145 // Allocate any still-undetermined frame elements to registers or
146 // memory, from the top down.
147 for (int i = length - 1; i >= 0; i--) {
148 if (elements[i] == NULL) {
149 // Loop over all the reaching frames to check whether the element
150 // is synced on all frames and to count the registers it occupies.
151 bool is_synced = true;
152 RegisterFile candidate_registers;
153 int best_count = kMinInt;
154 int best_reg_num = RegisterAllocator::kInvalidRegister;
155 NumberInfo info = NumberInfo::Uninitialized();
156
157 for (int j = 0; j < reaching_frames_.length(); j++) {
158 FrameElement element = reaching_frames_[j]->elements_[i];
159 if (direction_ == BIDIRECTIONAL) {
160 info = NumberInfo::Unknown();
161 } else if (!element.is_copy()) {
162 info = NumberInfo::Combine(info, element.number_info());
163 } else {
164 // New elements will not be copies, so get number information from
165 // backing element in the reaching frame.
166 info = NumberInfo::Combine(info,
167 reaching_frames_[j]->elements_[element.index()].number_info());
168 }
169 is_synced = is_synced && element.is_synced();
170 if (element.is_register() && !entry_frame_->is_used(element.reg())) {
171 // Count the register occurrence and remember it if better
172 // than the previous best.
173 int num = RegisterAllocator::ToNumber(element.reg());
174 candidate_registers.Use(num);
175 if (candidate_registers.count(num) > best_count) {
176 best_count = candidate_registers.count(num);
177 best_reg_num = num;
178 }
179 }
180 }
181
182 // We must have a number type information now (not for copied elements).
183 ASSERT(entry_frame_->elements_[i].is_copy()
184 || !info.IsUninitialized());
185
186 // If the value is synced on all frames, put it in memory. This
187 // costs nothing at the merge code but will incur a
188 // memory-to-register move when the value is needed later.
189 if (is_synced) {
190 // Already recorded as a memory element.
191 // Set combined number info.
192 entry_frame_->elements_[i].set_number_info(info);
193 continue;
194 }
195
196 // Try to put it in a register. If there was no best choice
197 // consider any free register.
198 if (best_reg_num == RegisterAllocator::kInvalidRegister) {
199 for (int j = 0; j < RegisterAllocator::kNumRegisters; j++) {
200 if (!entry_frame_->is_used(j)) {
201 best_reg_num = j;
202 break;
203 }
204 }
205 }
206
207 if (best_reg_num != RegisterAllocator::kInvalidRegister) {
208 // If there was a register choice, use it. Preserve the copied
209 // flag on the element.
210 bool is_copied = entry_frame_->elements_[i].is_copied();
211 Register reg = RegisterAllocator::ToRegister(best_reg_num);
212 entry_frame_->elements_[i] =
213 FrameElement::RegisterElement(reg, FrameElement::NOT_SYNCED,
214 NumberInfo::Uninitialized());
215 if (is_copied) entry_frame_->elements_[i].set_copied();
216 entry_frame_->set_register_location(reg, i);
217 }
218 // Set combined number info.
219 entry_frame_->elements_[i].set_number_info(info);
220 }
221 }
222
223 // If we have incoming backward edges assert we forget all number information.
224 #ifdef DEBUG
225 if (direction_ == BIDIRECTIONAL) {
226 for (int i = 0; i < length; ++i) {
227 if (!entry_frame_->elements_[i].is_copy()) {
228 ASSERT(entry_frame_->elements_[i].number_info().IsUnknown());
229 }
230 }
231 }
232 #endif
233
234 // The stack pointer is at the highest synced element or the base of
235 // the expression stack.
236 int stack_pointer = length - 1;
237 while (stack_pointer >= entry_frame_->expression_base_index() &&
238 !entry_frame_->elements_[stack_pointer].is_synced()) {
239 stack_pointer--;
240 }
241 entry_frame_->stack_pointer_ = stack_pointer;
242 }
243
244
245 void JumpTarget::Jump() { 51 void JumpTarget::Jump() {
246 DoJump(); 52 DoJump();
247 } 53 }
248 54
249 55
250 void JumpTarget::Jump(Result* arg) {
251 ASSERT(cgen()->has_valid_frame());
252
253 cgen()->frame()->Push(arg);
254 DoJump();
255 }
256
257
258 void JumpTarget::Branch(Condition cc, Hint hint) { 56 void JumpTarget::Branch(Condition cc, Hint hint) {
259 DoBranch(cc, hint); 57 DoBranch(cc, hint);
260 } 58 }
261 59
262 60
263 #ifdef DEBUG
264 #define DECLARE_ARGCHECK_VARS(name) \
265 Result::Type name##_type = name->type(); \
266 Register name##_reg = name->is_register() ? name->reg() : no_reg
267
268 #define ASSERT_ARGCHECK(name) \
269 ASSERT(name->type() == name##_type); \
270 ASSERT(!name->is_register() || name->reg().is(name##_reg))
271
272 #else
273 #define DECLARE_ARGCHECK_VARS(name) do {} while (false)
274
275 #define ASSERT_ARGCHECK(name) do {} while (false)
276 #endif
277
278 void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
279 ASSERT(cgen()->has_valid_frame());
280
281 // We want to check that non-frame registers at the call site stay in
282 // the same registers on the fall-through branch.
283 DECLARE_ARGCHECK_VARS(arg);
284
285 cgen()->frame()->Push(arg);
286 DoBranch(cc, hint);
287 *arg = cgen()->frame()->Pop();
288
289 ASSERT_ARGCHECK(arg);
290 }
291
292
293 void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
294 ASSERT(cgen()->has_valid_frame());
295
296 int count = cgen()->frame()->height() - expected_height_;
297 if (count > 0) {
298 // We negate and branch here rather than using DoBranch's negate
299 // and branch. This gives us a hook to remove statement state
300 // from the frame.
301 JumpTarget fall_through;
302 // Branch to fall through will not negate, because it is a
303 // forward-only target.
304 fall_through.Branch(NegateCondition(cc), NegateHint(hint));
305 Jump(arg); // May emit merge code here.
306 fall_through.Bind();
307 } else {
308 DECLARE_ARGCHECK_VARS(arg);
309 cgen()->frame()->Push(arg);
310 DoBranch(cc, hint);
311 *arg = cgen()->frame()->Pop();
312 ASSERT_ARGCHECK(arg);
313 }
314 }
315
316 #undef DECLARE_ARGCHECK_VARS
317 #undef ASSERT_ARGCHECK
318
319
320 void JumpTarget::Bind() { 61 void JumpTarget::Bind() {
321 DoBind(); 62 DoBind();
322 } 63 }
323 64
324 65
325 void JumpTarget::Bind(Result* arg) {
326 if (cgen()->has_valid_frame()) {
327 cgen()->frame()->Push(arg);
328 }
329 DoBind();
330 *arg = cgen()->frame()->Pop();
331 }
332
333
334 void JumpTarget::AddReachingFrame(VirtualFrame* frame) { 66 void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
335 ASSERT(reaching_frames_.length() == merge_labels_.length()); 67 ASSERT(reaching_frames_.length() == merge_labels_.length());
336 ASSERT(entry_frame_ == NULL); 68 ASSERT(entry_frame_ == NULL);
337 Label fresh; 69 Label fresh;
338 merge_labels_.Add(fresh); 70 merge_labels_.Add(fresh);
339 reaching_frames_.Add(frame); 71 reaching_frames_.Add(frame);
340 } 72 }
341 73
342 74
343 // ------------------------------------------------------------------------- 75 // -------------------------------------------------------------------------
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
414 temp.CopyTo(this); 146 temp.CopyTo(this);
415 temp.Unuse(); 147 temp.Unuse();
416 148
417 #ifdef DEBUG 149 #ifdef DEBUG
418 is_shadowing_ = false; 150 is_shadowing_ = false;
419 #endif 151 #endif
420 } 152 }
421 153
422 154
423 } } // namespace v8::internal 155 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/virtual-frame-ia32.h ('k') | src/jump-target-heavy.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698