OLD | NEW |
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 Loading... |
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(int mergable_elements) { | 51 void JumpTarget::ComputeEntryFrame() { |
52 // Given: a collection of frames reaching by forward CFG edges and | 52 // Given: a collection of frames reaching by forward CFG edges and |
53 // the directionality of the block. Compute: an entry frame for the | 53 // the directionality of the block. Compute: an entry frame for the |
54 // block. | 54 // block. |
55 | 55 |
56 Counters::compute_entry_frame.Increment(); | 56 Counters::compute_entry_frame.Increment(); |
57 #ifdef DEBUG | 57 #ifdef DEBUG |
58 if (compiling_deferred_code_) { | 58 if (compiling_deferred_code_) { |
59 ASSERT(reaching_frames_.length() > 1); | 59 ASSERT(reaching_frames_.length() > 1); |
60 VirtualFrame* frame = reaching_frames_[0]; | 60 VirtualFrame* frame = reaching_frames_[0]; |
61 bool all_identical = true; | 61 bool all_identical = true; |
62 for (int i = 1; i < reaching_frames_.length(); i++) { | 62 for (int i = 1; i < reaching_frames_.length(); i++) { |
63 if (!frame->Equals(reaching_frames_[i])) { | 63 if (!frame->Equals(reaching_frames_[i])) { |
64 all_identical = false; | 64 all_identical = false; |
65 break; | 65 break; |
66 } | 66 } |
67 } | 67 } |
68 ASSERT(!all_identical || all_identical); | 68 ASSERT(!all_identical || all_identical); |
69 } | 69 } |
70 #endif | 70 #endif |
71 | 71 |
72 // Choose an initial frame. | 72 // Choose an initial frame. |
73 VirtualFrame* initial_frame = reaching_frames_[0]; | 73 VirtualFrame* initial_frame = reaching_frames_[0]; |
74 | 74 |
75 // A list of pointers to frame elements in the entry frame. NULL | 75 // A list of pointers to frame elements in the entry frame. NULL |
76 // indicates that the element has not yet been determined. | 76 // indicates that the element has not yet been determined. |
77 int length = initial_frame->element_count(); | 77 int length = initial_frame->element_count(); |
78 ZoneList<FrameElement*> elements(length); | 78 ZoneList<FrameElement*> elements(length); |
79 | 79 |
80 // Convert the number of mergable elements (counted from the top | |
81 // down) to a frame high-water mark (counted from the bottom up). | |
82 // Elements strictly above the high-water index will be mergable in | |
83 // entry frames for bidirectional jump targets. | |
84 int high_water_mark = (mergable_elements == kAllElements) | |
85 ? VirtualFrame::kIllegalIndex // All frame indices are above this. | |
86 : length - mergable_elements - 1; // Top index if m_e == 0. | |
87 | |
88 // Initially populate the list of elements based on the initial | 80 // Initially populate the list of elements based on the initial |
89 // frame. | 81 // frame. |
90 for (int i = 0; i < length; i++) { | 82 for (int i = 0; i < length; i++) { |
91 FrameElement element = initial_frame->elements_[i]; | 83 FrameElement element = initial_frame->elements_[i]; |
92 // We do not allow copies or constants in bidirectional frames. All | 84 // We do not allow copies or constants in bidirectional frames. All |
93 // elements above the water mark on bidirectional frames have | 85 // elements above the water mark on bidirectional frames have |
94 // unknown static types. | 86 // unknown static types. |
95 if (direction_ == BIDIRECTIONAL && i > high_water_mark) { | 87 if (direction_ == BIDIRECTIONAL) { |
96 if (element.is_constant() || element.is_copy()) { | 88 if (element.is_constant() || element.is_copy()) { |
97 elements.Add(NULL); | 89 elements.Add(NULL); |
98 continue; | 90 continue; |
99 } | 91 } |
100 // It's safe to change the static type on the initial frame | 92 // It's safe to change the static type on the initial frame |
101 // element, see comment in JumpTarget::Combine. | 93 // element, see comment in JumpTarget::Combine. |
102 initial_frame->elements_[i].set_static_type(StaticType::unknown()); | 94 initial_frame->elements_[i].set_static_type(StaticType::unknown()); |
103 } | 95 } |
104 elements.Add(&initial_frame->elements_[i]); | 96 elements.Add(&initial_frame->elements_[i]); |
105 } | 97 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 if (elements[i] == NULL) { | 143 if (elements[i] == NULL) { |
152 // Loop over all the reaching frames to check whether the element | 144 // Loop over all the reaching frames to check whether the element |
153 // is synced on all frames, to count the registers it occupies, | 145 // is synced on all frames, to count the registers it occupies, |
154 // and to compute a merged static type. | 146 // and to compute a merged static type. |
155 bool is_synced = true; | 147 bool is_synced = true; |
156 RegisterFile candidate_registers; | 148 RegisterFile candidate_registers; |
157 int best_count = kMinInt; | 149 int best_count = kMinInt; |
158 int best_reg_num = RegisterAllocator::kInvalidRegister; | 150 int best_reg_num = RegisterAllocator::kInvalidRegister; |
159 | 151 |
160 StaticType type; // Initially invalid. | 152 StaticType type; // Initially invalid. |
161 if (direction_ != BIDIRECTIONAL || i < high_water_mark) { | 153 if (direction_ != BIDIRECTIONAL) { |
162 type = reaching_frames_[0]->elements_[i].static_type(); | 154 type = reaching_frames_[0]->elements_[i].static_type(); |
163 } | 155 } |
164 | 156 |
165 for (int j = 0; j < reaching_frames_.length(); j++) { | 157 for (int j = 0; j < reaching_frames_.length(); j++) { |
166 FrameElement element = reaching_frames_[j]->elements_[i]; | 158 FrameElement element = reaching_frames_[j]->elements_[i]; |
167 is_synced = is_synced && element.is_synced(); | 159 is_synced = is_synced && element.is_synced(); |
168 if (element.is_register() && !entry_frame_->is_used(element.reg())) { | 160 if (element.is_register() && !entry_frame_->is_used(element.reg())) { |
169 // Count the register occurrence and remember it if better | 161 // Count the register occurrence and remember it if better |
170 // than the previous best. | 162 // than the previous best. |
171 int num = RegisterAllocator::ToNumber(element.reg()); | 163 int num = RegisterAllocator::ToNumber(element.reg()); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 | 226 |
235 | 227 |
236 void JumpTarget::Jump(Result* arg) { | 228 void JumpTarget::Jump(Result* arg) { |
237 ASSERT(cgen()->has_valid_frame()); | 229 ASSERT(cgen()->has_valid_frame()); |
238 | 230 |
239 cgen()->frame()->Push(arg); | 231 cgen()->frame()->Push(arg); |
240 DoJump(); | 232 DoJump(); |
241 } | 233 } |
242 | 234 |
243 | 235 |
244 void JumpTarget::Jump(Result* arg0, Result* arg1) { | |
245 ASSERT(cgen()->has_valid_frame()); | |
246 | |
247 cgen()->frame()->Push(arg0); | |
248 cgen()->frame()->Push(arg1); | |
249 DoJump(); | |
250 } | |
251 | |
252 | |
253 void JumpTarget::Jump(Result* arg0, Result* arg1, Result* arg2) { | |
254 ASSERT(cgen()->has_valid_frame()); | |
255 | |
256 cgen()->frame()->Push(arg0); | |
257 cgen()->frame()->Push(arg1); | |
258 cgen()->frame()->Push(arg2); | |
259 DoJump(); | |
260 } | |
261 | |
262 | |
263 void JumpTarget::Branch(Condition cc, Hint hint) { | 236 void JumpTarget::Branch(Condition cc, Hint hint) { |
264 DoBranch(cc, hint); | 237 DoBranch(cc, hint); |
265 } | 238 } |
266 | 239 |
267 | 240 |
268 #ifdef DEBUG | 241 #ifdef DEBUG |
269 #define DECLARE_ARGCHECK_VARS(name) \ | 242 #define DECLARE_ARGCHECK_VARS(name) \ |
270 Result::Type name##_type = name->type(); \ | 243 Result::Type name##_type = name->type(); \ |
271 Register name##_reg = name->is_register() ? name->reg() : no_reg | 244 Register name##_reg = name->is_register() ? name->reg() : no_reg |
272 | 245 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 cgen()->frame()->Push(arg1); | 280 cgen()->frame()->Push(arg1); |
308 DoBranch(cc, hint); | 281 DoBranch(cc, hint); |
309 *arg1 = cgen()->frame()->Pop(); | 282 *arg1 = cgen()->frame()->Pop(); |
310 *arg0 = cgen()->frame()->Pop(); | 283 *arg0 = cgen()->frame()->Pop(); |
311 | 284 |
312 ASSERT_ARGCHECK(arg0); | 285 ASSERT_ARGCHECK(arg0); |
313 ASSERT_ARGCHECK(arg1); | 286 ASSERT_ARGCHECK(arg1); |
314 } | 287 } |
315 | 288 |
316 | 289 |
317 void JumpTarget::Branch(Condition cc, | |
318 Result* arg0, | |
319 Result* arg1, | |
320 Result* arg2, | |
321 Hint hint) { | |
322 ASSERT(cgen()->frame() != NULL); | |
323 | |
324 // We want to check that non-frame registers at the call site stay in | |
325 // the same registers on the fall-through branch. | |
326 DECLARE_ARGCHECK_VARS(arg0); | |
327 DECLARE_ARGCHECK_VARS(arg1); | |
328 DECLARE_ARGCHECK_VARS(arg2); | |
329 | |
330 cgen()->frame()->Push(arg0); | |
331 cgen()->frame()->Push(arg1); | |
332 cgen()->frame()->Push(arg2); | |
333 DoBranch(cc, hint); | |
334 *arg2 = cgen()->frame()->Pop(); | |
335 *arg1 = cgen()->frame()->Pop(); | |
336 *arg0 = cgen()->frame()->Pop(); | |
337 | |
338 ASSERT_ARGCHECK(arg0); | |
339 ASSERT_ARGCHECK(arg1); | |
340 ASSERT_ARGCHECK(arg2); | |
341 } | |
342 | |
343 | |
344 void JumpTarget::Branch(Condition cc, | |
345 Result* arg0, | |
346 Result* arg1, | |
347 Result* arg2, | |
348 Result* arg3, | |
349 Hint hint) { | |
350 ASSERT(cgen()->frame() != NULL); | |
351 | |
352 // We want to check that non-frame registers at the call site stay in | |
353 // the same registers on the fall-through branch. | |
354 DECLARE_ARGCHECK_VARS(arg0); | |
355 DECLARE_ARGCHECK_VARS(arg1); | |
356 DECLARE_ARGCHECK_VARS(arg2); | |
357 DECLARE_ARGCHECK_VARS(arg3); | |
358 | |
359 cgen()->frame()->Push(arg0); | |
360 cgen()->frame()->Push(arg1); | |
361 cgen()->frame()->Push(arg2); | |
362 cgen()->frame()->Push(arg3); | |
363 DoBranch(cc, hint); | |
364 *arg3 = cgen()->frame()->Pop(); | |
365 *arg2 = cgen()->frame()->Pop(); | |
366 *arg1 = cgen()->frame()->Pop(); | |
367 *arg0 = cgen()->frame()->Pop(); | |
368 | |
369 ASSERT_ARGCHECK(arg0); | |
370 ASSERT_ARGCHECK(arg1); | |
371 ASSERT_ARGCHECK(arg2); | |
372 ASSERT_ARGCHECK(arg3); | |
373 } | |
374 | |
375 | |
376 void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) { | 290 void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) { |
377 ASSERT(cgen()->has_valid_frame()); | 291 ASSERT(cgen()->has_valid_frame()); |
378 | 292 |
379 int count = cgen()->frame()->height() - expected_height_; | 293 int count = cgen()->frame()->height() - expected_height_; |
380 if (count > 0) { | 294 if (count > 0) { |
381 // We negate and branch here rather than using DoBranch's negate | 295 // We negate and branch here rather than using DoBranch's negate |
382 // and branch. This gives us a hook to remove statement state | 296 // and branch. This gives us a hook to remove statement state |
383 // from the frame. | 297 // from the frame. |
384 JumpTarget fall_through; | 298 JumpTarget fall_through; |
385 // Branch to fall through will not negate, because it is a | 299 // Branch to fall through will not negate, because it is a |
386 // forward-only target. | 300 // forward-only target. |
387 fall_through.Branch(NegateCondition(cc), NegateHint(hint)); | 301 fall_through.Branch(NegateCondition(cc), NegateHint(hint)); |
388 Jump(arg); // May emit merge code here. | 302 Jump(arg); // May emit merge code here. |
389 fall_through.Bind(); | 303 fall_through.Bind(); |
390 } else { | 304 } else { |
391 DECLARE_ARGCHECK_VARS(arg); | 305 DECLARE_ARGCHECK_VARS(arg); |
392 cgen()->frame()->Push(arg); | 306 cgen()->frame()->Push(arg); |
393 DoBranch(cc, hint); | 307 DoBranch(cc, hint); |
394 *arg = cgen()->frame()->Pop(); | 308 *arg = cgen()->frame()->Pop(); |
395 ASSERT_ARGCHECK(arg); | 309 ASSERT_ARGCHECK(arg); |
396 } | 310 } |
397 } | 311 } |
398 | 312 |
399 #undef DECLARE_ARGCHECK_VARS | 313 #undef DECLARE_ARGCHECK_VARS |
400 #undef ASSERT_ARGCHECK | 314 #undef ASSERT_ARGCHECK |
401 | 315 |
402 | 316 |
403 void JumpTarget::Bind(int mergable_elements) { | 317 void JumpTarget::Bind() { |
404 DoBind(mergable_elements); | 318 DoBind(); |
405 } | 319 } |
406 | 320 |
407 | 321 |
408 void JumpTarget::Bind(Result* arg, int mergable_elements) { | 322 void JumpTarget::Bind(Result* arg) { |
409 if (cgen()->has_valid_frame()) { | 323 if (cgen()->has_valid_frame()) { |
410 cgen()->frame()->Push(arg); | 324 cgen()->frame()->Push(arg); |
411 } | 325 } |
412 DoBind(mergable_elements); | 326 DoBind(); |
413 *arg = cgen()->frame()->Pop(); | 327 *arg = cgen()->frame()->Pop(); |
414 } | 328 } |
415 | 329 |
416 | 330 |
417 void JumpTarget::Bind(Result* arg0, Result* arg1, int mergable_elements) { | 331 void JumpTarget::Bind(Result* arg0, Result* arg1) { |
418 if (cgen()->has_valid_frame()) { | 332 if (cgen()->has_valid_frame()) { |
419 cgen()->frame()->Push(arg0); | 333 cgen()->frame()->Push(arg0); |
420 cgen()->frame()->Push(arg1); | 334 cgen()->frame()->Push(arg1); |
421 } | 335 } |
422 DoBind(mergable_elements); | 336 DoBind(); |
423 *arg1 = cgen()->frame()->Pop(); | |
424 *arg0 = cgen()->frame()->Pop(); | |
425 } | |
426 | |
427 | |
428 void JumpTarget::Bind(Result* arg0, | |
429 Result* arg1, | |
430 Result* arg2, | |
431 int mergable_elements) { | |
432 if (cgen()->has_valid_frame()) { | |
433 cgen()->frame()->Push(arg0); | |
434 cgen()->frame()->Push(arg1); | |
435 cgen()->frame()->Push(arg2); | |
436 } | |
437 DoBind(mergable_elements); | |
438 *arg2 = cgen()->frame()->Pop(); | |
439 *arg1 = cgen()->frame()->Pop(); | |
440 *arg0 = cgen()->frame()->Pop(); | |
441 } | |
442 | |
443 | |
444 void JumpTarget::Bind(Result* arg0, | |
445 Result* arg1, | |
446 Result* arg2, | |
447 Result* arg3, | |
448 int mergable_elements) { | |
449 if (cgen()->has_valid_frame()) { | |
450 cgen()->frame()->Push(arg0); | |
451 cgen()->frame()->Push(arg1); | |
452 cgen()->frame()->Push(arg2); | |
453 cgen()->frame()->Push(arg3); | |
454 } | |
455 DoBind(mergable_elements); | |
456 *arg3 = cgen()->frame()->Pop(); | |
457 *arg2 = cgen()->frame()->Pop(); | |
458 *arg1 = cgen()->frame()->Pop(); | 337 *arg1 = cgen()->frame()->Pop(); |
459 *arg0 = cgen()->frame()->Pop(); | 338 *arg0 = cgen()->frame()->Pop(); |
460 } | 339 } |
461 | 340 |
462 | 341 |
463 void JumpTarget::AddReachingFrame(VirtualFrame* frame) { | 342 void JumpTarget::AddReachingFrame(VirtualFrame* frame) { |
464 ASSERT(reaching_frames_.length() == merge_labels_.length()); | 343 ASSERT(reaching_frames_.length() == merge_labels_.length()); |
465 ASSERT(entry_frame_ == NULL); | 344 ASSERT(entry_frame_ == NULL); |
466 Label fresh; | 345 Label fresh; |
467 merge_labels_.Add(fresh); | 346 merge_labels_.Add(fresh); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 // forward-only target. | 403 // forward-only target. |
525 fall_through.Branch(NegateCondition(cc), NegateHint(hint)); | 404 fall_through.Branch(NegateCondition(cc), NegateHint(hint)); |
526 Jump(); // May emit merge code here. | 405 Jump(); // May emit merge code here. |
527 fall_through.Bind(); | 406 fall_through.Bind(); |
528 } else { | 407 } else { |
529 DoBranch(cc, hint); | 408 DoBranch(cc, hint); |
530 } | 409 } |
531 } | 410 } |
532 | 411 |
533 | 412 |
534 void BreakTarget::Bind(int mergable_elements) { | 413 void BreakTarget::Bind() { |
535 #ifdef DEBUG | 414 #ifdef DEBUG |
536 // All the forward-reaching frames should have been adjusted at the | 415 // All the forward-reaching frames should have been adjusted at the |
537 // jumps to this target. | 416 // jumps to this target. |
538 for (int i = 0; i < reaching_frames_.length(); i++) { | 417 for (int i = 0; i < reaching_frames_.length(); i++) { |
539 ASSERT(reaching_frames_[i] == NULL || | 418 ASSERT(reaching_frames_[i] == NULL || |
540 reaching_frames_[i]->height() == expected_height_); | 419 reaching_frames_[i]->height() == expected_height_); |
541 } | 420 } |
542 #endif | 421 #endif |
543 // Drop leftover statement state from the frame before merging, even | 422 // Drop leftover statement state from the frame before merging, even |
544 // on the fall through. This is so we can bind the return target | 423 // on the fall through. This is so we can bind the return target |
545 // with state on the frame. | 424 // with state on the frame. |
546 if (cgen()->has_valid_frame()) { | 425 if (cgen()->has_valid_frame()) { |
547 int count = cgen()->frame()->height() - expected_height_; | 426 int count = cgen()->frame()->height() - expected_height_; |
548 cgen()->frame()->ForgetElements(count); | 427 cgen()->frame()->ForgetElements(count); |
549 } | 428 } |
550 DoBind(mergable_elements); | 429 DoBind(); |
551 } | 430 } |
552 | 431 |
553 | 432 |
554 void BreakTarget::Bind(Result* arg, int mergable_elements) { | 433 void BreakTarget::Bind(Result* arg) { |
555 #ifdef DEBUG | 434 #ifdef DEBUG |
556 // All the forward-reaching frames should have been adjusted at the | 435 // All the forward-reaching frames should have been adjusted at the |
557 // jumps to this target. | 436 // jumps to this target. |
558 for (int i = 0; i < reaching_frames_.length(); i++) { | 437 for (int i = 0; i < reaching_frames_.length(); i++) { |
559 ASSERT(reaching_frames_[i] == NULL || | 438 ASSERT(reaching_frames_[i] == NULL || |
560 reaching_frames_[i]->height() == expected_height_ + 1); | 439 reaching_frames_[i]->height() == expected_height_ + 1); |
561 } | 440 } |
562 #endif | 441 #endif |
563 // Drop leftover statement state from the frame before merging, even | 442 // Drop leftover statement state from the frame before merging, even |
564 // on the fall through. This is so we can bind the return target | 443 // on the fall through. This is so we can bind the return target |
565 // with state on the frame. | 444 // with state on the frame. |
566 if (cgen()->has_valid_frame()) { | 445 if (cgen()->has_valid_frame()) { |
567 int count = cgen()->frame()->height() - expected_height_; | 446 int count = cgen()->frame()->height() - expected_height_; |
568 cgen()->frame()->ForgetElements(count); | 447 cgen()->frame()->ForgetElements(count); |
569 cgen()->frame()->Push(arg); | 448 cgen()->frame()->Push(arg); |
570 } | 449 } |
571 DoBind(mergable_elements); | 450 DoBind(); |
572 *arg = cgen()->frame()->Pop(); | 451 *arg = cgen()->frame()->Pop(); |
573 } | 452 } |
574 | 453 |
575 | 454 |
576 // ------------------------------------------------------------------------- | 455 // ------------------------------------------------------------------------- |
577 // ShadowTarget implementation. | 456 // ShadowTarget implementation. |
578 | 457 |
579 ShadowTarget::ShadowTarget(BreakTarget* shadowed) { | 458 ShadowTarget::ShadowTarget(BreakTarget* shadowed) { |
580 ASSERT(shadowed != NULL); | 459 ASSERT(shadowed != NULL); |
581 other_target_ = shadowed; | 460 other_target_ = shadowed; |
(...skipping 22 matching lines...) Expand all Loading... |
604 temp.CopyTo(this); | 483 temp.CopyTo(this); |
605 temp.Unuse(); | 484 temp.Unuse(); |
606 | 485 |
607 #ifdef DEBUG | 486 #ifdef DEBUG |
608 is_shadowing_ = false; | 487 is_shadowing_ = false; |
609 #endif | 488 #endif |
610 } | 489 } |
611 | 490 |
612 | 491 |
613 } } // namespace v8::internal | 492 } } // namespace v8::internal |
OLD | NEW |