| OLD | NEW |
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 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 24 matching lines...) Expand all Loading... |
| 35 // ------------------------------------------------------------------------- | 35 // ------------------------------------------------------------------------- |
| 36 // JumpTarget implementation. | 36 // JumpTarget implementation. |
| 37 | 37 |
| 38 #define __ masm_-> | 38 #define __ masm_-> |
| 39 | 39 |
| 40 JumpTarget::JumpTarget(CodeGenerator* cgen, Directionality direction) | 40 JumpTarget::JumpTarget(CodeGenerator* cgen, Directionality direction) |
| 41 : cgen_(cgen), | 41 : cgen_(cgen), |
| 42 direction_(direction), | 42 direction_(direction), |
| 43 reaching_frames_(0), | 43 reaching_frames_(0), |
| 44 merge_labels_(0), | 44 merge_labels_(0), |
| 45 expected_frame_(NULL) { | 45 expected_frame_(NULL), |
| 46 is_bound_(false), |
| 47 is_linked_(false) { |
| 46 ASSERT(cgen_ != NULL); | 48 ASSERT(cgen_ != NULL); |
| 47 masm_ = cgen_->masm(); | 49 masm_ = cgen_->masm(); |
| 48 } | 50 } |
| 49 | 51 |
| 50 | 52 |
| 51 JumpTarget::JumpTarget() | 53 JumpTarget::JumpTarget() |
| 52 : cgen_(NULL), | 54 : cgen_(NULL), |
| 53 masm_(NULL), | 55 masm_(NULL), |
| 54 direction_(FORWARD_ONLY), | 56 direction_(FORWARD_ONLY), |
| 55 reaching_frames_(0), | 57 reaching_frames_(0), |
| 56 merge_labels_(0), | 58 merge_labels_(0), |
| 57 expected_frame_(NULL) { | 59 expected_frame_(NULL), |
| 60 is_bound_(false), |
| 61 is_linked_(false) { |
| 58 } | 62 } |
| 59 | 63 |
| 60 | 64 |
| 61 void JumpTarget::Initialize(CodeGenerator* cgen, Directionality direction) { | 65 void JumpTarget::Initialize(CodeGenerator* cgen, Directionality direction) { |
| 62 ASSERT(cgen != NULL); | 66 ASSERT(cgen != NULL); |
| 63 ASSERT(cgen_ == NULL); | 67 ASSERT(cgen_ == NULL); |
| 64 cgen_ = cgen; | 68 cgen_ = cgen; |
| 65 masm_ = cgen->masm(); | 69 masm_ = cgen->masm(); |
| 66 direction_ = direction; | 70 direction_ = direction; |
| 67 } | 71 } |
| 68 | 72 |
| 69 | 73 |
| 74 void JumpTarget::Unuse() { |
| 75 ASSERT(!is_linked()); |
| 76 entry_label_.Unuse(); |
| 77 delete expected_frame_; |
| 78 expected_frame_ = NULL; |
| 79 is_bound_ = false; |
| 80 is_linked_ = false; |
| 81 } |
| 82 |
| 83 |
| 84 void JumpTarget::Reset() { |
| 85 reaching_frames_.Clear(); |
| 86 merge_labels_.Clear(); |
| 87 expected_frame_ = NULL; |
| 88 entry_label_.Unuse(); |
| 89 is_bound_ = false; |
| 90 is_linked_ = false; |
| 91 } |
| 92 |
| 93 |
| 70 void JumpTarget::Jump() { | 94 void JumpTarget::Jump() { |
| 71 ASSERT(cgen_ != NULL); | 95 ASSERT(cgen_ != NULL); |
| 72 ASSERT(cgen_->has_valid_frame()); | 96 ASSERT(cgen_->has_valid_frame()); |
| 73 // Live non-frame registers are not allowed at unconditional jumps | 97 // Live non-frame registers are not allowed at unconditional jumps |
| 74 // because we have no way of invalidating the corresponding results | 98 // because we have no way of invalidating the corresponding results |
| 75 // which are still live in the C++ code. | 99 // which are still live in the C++ code. |
| 76 ASSERT(cgen_->HasValidEntryRegisters()); | 100 ASSERT(cgen_->HasValidEntryRegisters()); |
| 77 | 101 |
| 78 if (is_bound()) { | 102 if (is_bound()) { |
| 79 // Backward jump. There is an expected frame to merge to. | 103 // Backward jump. There is an expected frame to merge to. |
| 80 ASSERT(direction_ == BIDIRECTIONAL); | 104 ASSERT(direction_ == BIDIRECTIONAL); |
| 81 cgen_->frame()->MergeTo(expected_frame_); | 105 cgen_->frame()->MergeTo(expected_frame_); |
| 82 cgen_->DeleteFrame(); | 106 cgen_->DeleteFrame(); |
| 83 __ jmp(&entry_label_); | 107 __ jmp(&entry_label_); |
| 84 } else { | 108 } else { |
| 85 // Forward jump. The current frame is added to the end of the list | 109 // Forward jump. The current frame is added to the end of the list |
| 86 // of frames reaching the target block and a jump to the merge code | 110 // of frames reaching the target block and a jump to the merge code |
| 87 // is emitted. | 111 // is emitted. |
| 88 AddReachingFrame(cgen_->frame()); | 112 AddReachingFrame(cgen_->frame()); |
| 89 RegisterFile empty; | 113 RegisterFile empty; |
| 90 cgen_->SetFrame(NULL, &empty); | 114 cgen_->SetFrame(NULL, &empty); |
| 91 __ jmp(&merge_labels_.last()); | 115 __ jmp(&merge_labels_.last()); |
| 92 } | 116 } |
| 117 |
| 118 is_linked_ = !is_bound_; |
| 93 } | 119 } |
| 94 | 120 |
| 95 | 121 |
| 96 void JumpTarget::Jump(Result* arg) { | 122 void JumpTarget::Jump(Result* arg) { |
| 97 ASSERT(cgen_ != NULL); | 123 ASSERT(cgen_ != NULL); |
| 98 ASSERT(cgen_->has_valid_frame()); | 124 ASSERT(cgen_->has_valid_frame()); |
| 99 | 125 |
| 100 cgen_->frame()->Push(arg); | 126 cgen_->frame()->Push(arg); |
| 101 Jump(); | 127 Jump(); |
| 102 } | 128 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 // Restore the frame and its associated non-frame registers. | 179 // Restore the frame and its associated non-frame registers. |
| 154 cgen_->SetFrame(original_frame, &non_frame_registers); | 180 cgen_->SetFrame(original_frame, &non_frame_registers); |
| 155 __ bind(&original_fall_through); | 181 __ bind(&original_fall_through); |
| 156 } else { | 182 } else { |
| 157 // Forward branch. A copy of the current frame is added to the end | 183 // Forward branch. A copy of the current frame is added to the end |
| 158 // of the list of frames reaching the target block and a branch to | 184 // of the list of frames reaching the target block and a branch to |
| 159 // the merge code is emitted. | 185 // the merge code is emitted. |
| 160 AddReachingFrame(new VirtualFrame(cgen_->frame())); | 186 AddReachingFrame(new VirtualFrame(cgen_->frame())); |
| 161 __ j(cc, &merge_labels_.last(), hint); | 187 __ j(cc, &merge_labels_.last(), hint); |
| 162 } | 188 } |
| 189 |
| 190 is_linked_ = !is_bound_; |
| 163 } | 191 } |
| 164 | 192 |
| 165 | 193 |
| 166 #ifdef DEBUG | 194 #ifdef DEBUG |
| 167 #define DECLARE_ARGCHECK_VARS(name) \ | 195 #define DECLARE_ARGCHECK_VARS(name) \ |
| 168 Result::Type name##_type = name->type(); \ | 196 Result::Type name##_type = name->type(); \ |
| 169 Register name##_reg = name->is_register() ? name->reg() : no_reg | 197 Register name##_reg = name->is_register() ? name->reg() : no_reg |
| 170 | 198 |
| 171 #define ASSERT_ARGCHECK(name) \ | 199 #define ASSERT_ARGCHECK(name) \ |
| 172 ASSERT(name->type() == name##_type); \ | 200 ASSERT(name->type() == name##_type); \ |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 ASSERT(cgen_->has_valid_frame()); | 319 ASSERT(cgen_->has_valid_frame()); |
| 292 // There are no non-frame references across the call. | 320 // There are no non-frame references across the call. |
| 293 ASSERT(cgen_->HasValidEntryRegisters()); | 321 ASSERT(cgen_->HasValidEntryRegisters()); |
| 294 ASSERT(!is_linked()); | 322 ASSERT(!is_linked()); |
| 295 | 323 |
| 296 cgen_->frame()->SpillAll(); | 324 cgen_->frame()->SpillAll(); |
| 297 VirtualFrame* target_frame = new VirtualFrame(cgen_->frame()); | 325 VirtualFrame* target_frame = new VirtualFrame(cgen_->frame()); |
| 298 target_frame->Adjust(1); | 326 target_frame->Adjust(1); |
| 299 AddReachingFrame(target_frame); | 327 AddReachingFrame(target_frame); |
| 300 __ call(&merge_labels_.last()); | 328 __ call(&merge_labels_.last()); |
| 329 |
| 330 is_linked_ = !is_bound_; |
| 301 } | 331 } |
| 302 | 332 |
| 303 | 333 |
| 304 void JumpTarget::Bind() { | 334 void JumpTarget::Bind() { |
| 305 ASSERT(cgen_ != NULL); | 335 ASSERT(cgen_ != NULL); |
| 306 ASSERT(is_linked() || cgen_->has_valid_frame()); | |
| 307 ASSERT(!is_bound()); | 336 ASSERT(!is_bound()); |
| 308 | 337 |
| 309 if (is_linked()) { | 338 if (is_linked()) { |
| 310 // There were forward jumps. A mergable frame is created and all | 339 // There were forward jumps. A mergable frame is created and all |
| 311 // the frames reaching the block via forward jumps are merged to it. | 340 // the frames reaching the block via forward jumps are merged to it. |
| 312 ASSERT(reaching_frames_.length() == merge_labels_.length()); | 341 ASSERT(reaching_frames_.length() == merge_labels_.length()); |
| 313 | 342 |
| 314 // Choose a frame as the basis of the expected frame, and make it | 343 // A special case is that there was only one jump to the block so |
| 315 // mergable. If there is a current frame use it, otherwise use the | 344 // far, no fall-through, and there cannot be another entry because |
| 316 // first in the list (there will be at least one). | 345 // the block is forward only. In that case, simply use the single |
| 317 int start_index = 0; | 346 // frame. |
| 318 if (cgen_->has_valid_frame()) { | 347 bool single_entry = (direction_ == FORWARD_ONLY) && |
| 319 // Live non-frame registers are not allowed at the start of a labeled | 348 !cgen_->has_valid_frame() && |
| 320 // basic block. | 349 (reaching_frames_.length() == 1); |
| 321 ASSERT(cgen_->HasValidEntryRegisters()); | 350 if (single_entry) { |
| 351 // Pick up the only forward reaching frame and bind its merge |
| 352 // label. No merge code is emitted. |
| 353 RegisterFile reserved_registers = RegisterAllocator::Reserved(); |
| 354 cgen_->SetFrame(reaching_frames_[0], &reserved_registers); |
| 355 __ bind(&merge_labels_[0]); |
| 322 } else { | 356 } else { |
| 323 RegisterFile reserved_registers = RegisterAllocator::Reserved(); | 357 // Otherwise, choose a frame as the basis of the expected frame, |
| 324 cgen_->SetFrame(reaching_frames_[start_index], &reserved_registers); | 358 // and make it mergable. If there is a current frame use it, |
| 325 __ bind(&merge_labels_[start_index++]); | 359 // otherwise use the first in the list (there will be at least |
| 360 // one). |
| 361 int start_index = 0; |
| 362 if (cgen_->has_valid_frame()) { |
| 363 // Live non-frame registers are not allowed at the start of a |
| 364 // labeled basic block. |
| 365 ASSERT(cgen_->HasValidEntryRegisters()); |
| 366 } else { |
| 367 RegisterFile reserved_registers = RegisterAllocator::Reserved(); |
| 368 cgen_->SetFrame(reaching_frames_[start_index], &reserved_registers); |
| 369 __ bind(&merge_labels_[start_index++]); |
| 370 } |
| 371 cgen_->frame()->MakeMergable(); |
| 372 expected_frame_ = new VirtualFrame(cgen_->frame()); |
| 373 |
| 374 for (int i = start_index; i < reaching_frames_.length(); i++) { |
| 375 cgen_->DeleteFrame(); |
| 376 __ jmp(&entry_label_); |
| 377 |
| 378 RegisterFile reserved_registers = RegisterAllocator::Reserved(); |
| 379 cgen_->SetFrame(reaching_frames_[i], &reserved_registers); |
| 380 __ bind(&merge_labels_[i]); |
| 381 |
| 382 cgen_->frame()->MergeTo(expected_frame_); |
| 383 } |
| 384 |
| 385 __ bind(&entry_label_); |
| 326 } | 386 } |
| 327 cgen_->frame()->MakeMergable(); | |
| 328 expected_frame_ = new VirtualFrame(cgen_->frame()); | |
| 329 | |
| 330 for (int i = start_index; i < reaching_frames_.length(); i++) { | |
| 331 cgen_->DeleteFrame(); | |
| 332 __ jmp(&entry_label_); | |
| 333 | |
| 334 RegisterFile reserved_registers = RegisterAllocator::Reserved(); | |
| 335 cgen_->SetFrame(reaching_frames_[i], &reserved_registers); | |
| 336 __ bind(&merge_labels_[i]); | |
| 337 | |
| 338 cgen_->frame()->MergeTo(expected_frame_); | |
| 339 } | |
| 340 __ bind(&entry_label_); | |
| 341 | 387 |
| 342 // All but the last reaching virtual frame have been deleted, and | 388 // All but the last reaching virtual frame have been deleted, and |
| 343 // the last one is the current frame. | 389 // the last one is the current frame. |
| 344 reaching_frames_.Clear(); | 390 reaching_frames_.Clear(); |
| 345 merge_labels_.Clear(); | 391 merge_labels_.Clear(); |
| 392 |
| 346 } else { | 393 } else { |
| 347 // There were no forward jumps. There must be a current frame, | 394 // There were no forward jumps. If this jump target is not |
| 348 // which is made mergable and used as the expected frame. | 395 // bidirectional, there is no need to do anything. For |
| 349 ASSERT(cgen_->HasValidEntryRegisters()); | 396 // bidirectional jump targets, the current frame is made mergable |
| 350 cgen_->frame()->MakeMergable(); | 397 // and used for the expected frame. |
| 351 expected_frame_ = new VirtualFrame(cgen_->frame()); | 398 if (direction_ == BIDIRECTIONAL) { |
| 352 __ bind(&entry_label_); | 399 ASSERT(cgen_->HasValidEntryRegisters()); |
| 400 cgen_->frame()->MakeMergable(); |
| 401 expected_frame_ = new VirtualFrame(cgen_->frame()); |
| 402 __ bind(&entry_label_); |
| 403 } |
| 353 } | 404 } |
| 405 |
| 406 is_linked_ = false; |
| 407 is_bound_ = true; |
| 354 } | 408 } |
| 355 | 409 |
| 356 | 410 |
| 357 void JumpTarget::Bind(Result* arg) { | 411 void JumpTarget::Bind(Result* arg) { |
| 358 ASSERT(cgen_ != NULL); | 412 ASSERT(cgen_ != NULL); |
| 359 | 413 |
| 360 if (cgen_->has_valid_frame()) { | 414 if (cgen_->has_valid_frame()) { |
| 361 cgen_->frame()->Push(arg); | 415 cgen_->frame()->Push(arg); |
| 362 } | 416 } |
| 363 Bind(); | 417 Bind(); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 destination->direction_ = direction_; | 471 destination->direction_ = direction_; |
| 418 destination->reaching_frames_.Clear(); | 472 destination->reaching_frames_.Clear(); |
| 419 destination->merge_labels_.Clear(); | 473 destination->merge_labels_.Clear(); |
| 420 ASSERT(reaching_frames_.length() == merge_labels_.length()); | 474 ASSERT(reaching_frames_.length() == merge_labels_.length()); |
| 421 for (int i = 0; i < reaching_frames_.length(); i++) { | 475 for (int i = 0; i < reaching_frames_.length(); i++) { |
| 422 destination->reaching_frames_.Add(reaching_frames_[i]); | 476 destination->reaching_frames_.Add(reaching_frames_[i]); |
| 423 destination->merge_labels_.Add(merge_labels_[i]); | 477 destination->merge_labels_.Add(merge_labels_[i]); |
| 424 } | 478 } |
| 425 destination->expected_frame_ = expected_frame_; | 479 destination->expected_frame_ = expected_frame_; |
| 426 destination->entry_label_ = entry_label_; | 480 destination->entry_label_ = entry_label_; |
| 481 destination->is_bound_ = is_bound_; |
| 482 destination->is_linked_ = is_linked_; |
| 427 } | 483 } |
| 428 | 484 |
| 429 | 485 |
| 430 void JumpTarget::AddReachingFrame(VirtualFrame* frame) { | 486 void JumpTarget::AddReachingFrame(VirtualFrame* frame) { |
| 431 ASSERT(reaching_frames_.length() == merge_labels_.length()); | 487 ASSERT(reaching_frames_.length() == merge_labels_.length()); |
| 432 Label fresh; | 488 Label fresh; |
| 433 merge_labels_.Add(fresh); | 489 merge_labels_.Add(fresh); |
| 434 reaching_frames_.Add(frame); | 490 reaching_frames_.Add(frame); |
| 435 } | 491 } |
| 436 | 492 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 | 534 |
| 479 #ifdef DEBUG | 535 #ifdef DEBUG |
| 480 is_shadowing_ = false; | 536 is_shadowing_ = false; |
| 481 #endif | 537 #endif |
| 482 } | 538 } |
| 483 | 539 |
| 484 #undef __ | 540 #undef __ |
| 485 | 541 |
| 486 | 542 |
| 487 } } // namespace v8::internal | 543 } } // namespace v8::internal |
| OLD | NEW |