OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
6 | 6 |
7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
9 #include "src/interpreter/bytecode-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.h" |
10 #include "src/interpreter/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 } while (current != nullptr); | 366 } while (current != nullptr); |
367 UNREACHABLE(); | 367 UNREACHABLE(); |
368 } | 368 } |
369 | 369 |
370 | 370 |
371 class BytecodeGenerator::RegisterAllocationScope { | 371 class BytecodeGenerator::RegisterAllocationScope { |
372 public: | 372 public: |
373 explicit RegisterAllocationScope(BytecodeGenerator* generator) | 373 explicit RegisterAllocationScope(BytecodeGenerator* generator) |
374 : generator_(generator), | 374 : generator_(generator), |
375 outer_(generator->register_allocator()), | 375 outer_(generator->register_allocator()), |
376 allocator_(builder()) { | 376 allocator_(builder()->zone(), |
| 377 builder()->temporary_register_allocator()) { |
377 generator_->set_register_allocator(this); | 378 generator_->set_register_allocator(this); |
378 } | 379 } |
379 | 380 |
380 virtual ~RegisterAllocationScope() { | 381 virtual ~RegisterAllocationScope() { |
381 generator_->set_register_allocator(outer_); | 382 generator_->set_register_allocator(outer_); |
382 } | 383 } |
383 | 384 |
384 Register NewRegister() { | 385 Register NewRegister() { |
385 RegisterAllocationScope* current_scope = generator()->register_allocator(); | 386 RegisterAllocationScope* current_scope = generator()->register_allocator(); |
386 if ((current_scope == this) || | 387 if ((current_scope == this) || |
387 (current_scope->outer() == this && | 388 (current_scope->outer() == this && |
388 !current_scope->allocator_.HasConsecutiveAllocations())) { | 389 !current_scope->allocator_.HasConsecutiveAllocations())) { |
389 // Regular case - Allocating registers in current or outer context. | 390 // Regular case - Allocating registers in current or outer context. |
390 // VisitForRegisterValue allocates register in outer context. | 391 // VisitForRegisterValue allocates register in outer context. |
391 return allocator_.NewRegister(); | 392 return allocator_.NewRegister(); |
392 } else { | 393 } else { |
393 // If it is required to allocate a register other than current or outer | 394 // If it is required to allocate a register other than current or outer |
394 // scopes, allocate a new temporary register. It might be expensive to | 395 // scopes, allocate a new temporary register. It might be expensive to |
395 // walk the full context chain and compute the list of consecutive | 396 // walk the full context chain and compute the list of consecutive |
396 // reservations in the innerscopes. | 397 // reservations in the innerscopes. |
397 UNIMPLEMENTED(); | 398 UNIMPLEMENTED(); |
398 return Register(-1); | 399 return Register::invalid_value(); |
399 } | 400 } |
400 } | 401 } |
401 | 402 |
402 void PrepareForConsecutiveAllocations(size_t count) { | 403 void PrepareForConsecutiveAllocations(int count) { |
403 allocator_.PrepareForConsecutiveAllocations(count); | 404 allocator_.PrepareForConsecutiveAllocations(count); |
404 } | 405 } |
405 | 406 |
406 Register NextConsecutiveRegister() { | 407 Register NextConsecutiveRegister() { |
407 return allocator_.NextConsecutiveRegister(); | 408 return allocator_.NextConsecutiveRegister(); |
408 } | 409 } |
409 | 410 |
410 bool RegisterIsAllocatedInThisScope(Register reg) const { | 411 bool RegisterIsAllocatedInThisScope(Register reg) const { |
411 return allocator_.RegisterIsAllocatedInThisScope(reg); | 412 return allocator_.RegisterIsAllocatedInThisScope(reg); |
412 } | 413 } |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 : ExpressionResultScope(generator, Expression::kValue) {} | 514 : ExpressionResultScope(generator, Expression::kValue) {} |
514 | 515 |
515 virtual void SetResultInAccumulator() { | 516 virtual void SetResultInAccumulator() { |
516 result_register_ = allocator()->outer()->NewRegister(); | 517 result_register_ = allocator()->outer()->NewRegister(); |
517 builder()->StoreAccumulatorInRegister(result_register_); | 518 builder()->StoreAccumulatorInRegister(result_register_); |
518 set_result_identified(); | 519 set_result_identified(); |
519 } | 520 } |
520 | 521 |
521 virtual void SetResultInRegister(Register reg) { | 522 virtual void SetResultInRegister(Register reg) { |
522 DCHECK(builder()->RegisterIsParameterOrLocal(reg) || | 523 DCHECK(builder()->RegisterIsParameterOrLocal(reg) || |
523 (builder()->RegisterIsTemporary(reg) && | 524 (builder()->TemporaryRegisterIsLive(reg) && |
524 !allocator()->RegisterIsAllocatedInThisScope(reg))); | 525 !allocator()->RegisterIsAllocatedInThisScope(reg))); |
525 result_register_ = reg; | 526 result_register_ = reg; |
526 set_result_identified(); | 527 set_result_identified(); |
527 } | 528 } |
528 | 529 |
529 Register ResultRegister() const { return result_register_; } | 530 Register ResultRegister() const { return result_register_; } |
530 | 531 |
531 private: | 532 private: |
532 Register result_register_; | 533 Register result_register_; |
533 }; | 534 }; |
534 | 535 |
535 | |
536 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) | 536 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) |
537 : isolate_(isolate), | 537 : isolate_(isolate), |
538 zone_(zone), | 538 zone_(zone), |
539 builder_(isolate, zone), | 539 builder_(nullptr), |
540 info_(nullptr), | 540 info_(nullptr), |
541 scope_(nullptr), | 541 scope_(nullptr), |
542 globals_(0, zone), | 542 globals_(0, zone), |
543 execution_control_(nullptr), | 543 execution_control_(nullptr), |
544 execution_context_(nullptr), | 544 execution_context_(nullptr), |
545 execution_result_(nullptr), | 545 execution_result_(nullptr), |
546 register_allocator_(nullptr) { | 546 register_allocator_(nullptr) { |
547 InitializeAstVisitor(isolate); | 547 InitializeAstVisitor(isolate); |
548 } | 548 } |
549 | 549 |
550 | 550 |
551 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { | 551 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { |
552 set_info(info); | 552 set_info(info); |
553 set_scope(info->scope()); | 553 set_scope(info->scope()); |
554 | 554 |
| 555 // Initialize bytecode array builder. |
| 556 set_builder(new (zone()) BytecodeArrayBuilder( |
| 557 isolate(), zone(), info->num_parameters_including_this(), |
| 558 scope()->MaxNestedContextChainLength(), scope()->num_stack_slots())); |
| 559 |
555 // Initialize the incoming context. | 560 // Initialize the incoming context. |
556 ContextScope incoming_context(this, scope(), false); | 561 ContextScope incoming_context(this, scope(), false); |
557 | 562 |
558 // Initialize control scope. | 563 // Initialize control scope. |
559 ControlScopeForTopLevel control(this); | 564 ControlScopeForTopLevel control(this); |
560 | 565 |
561 builder()->set_parameter_count(info->num_parameters_including_this()); | |
562 builder()->set_locals_count(scope()->num_stack_slots()); | |
563 builder()->set_context_count(scope()->MaxNestedContextChainLength()); | |
564 | |
565 // Build function context only if there are context allocated variables. | 566 // Build function context only if there are context allocated variables. |
566 if (scope()->NeedsContext()) { | 567 if (scope()->NeedsContext()) { |
567 // Push a new inner context scope for the function. | 568 // Push a new inner context scope for the function. |
568 VisitNewLocalFunctionContext(); | 569 VisitNewLocalFunctionContext(); |
569 ContextScope local_function_context(this, scope(), false); | 570 ContextScope local_function_context(this, scope(), false); |
570 VisitBuildLocalActivationContext(); | 571 VisitBuildLocalActivationContext(); |
571 MakeBytecodeBody(); | 572 MakeBytecodeBody(); |
572 } else { | 573 } else { |
573 MakeBytecodeBody(); | 574 MakeBytecodeBody(); |
574 } | 575 } |
575 | 576 |
576 set_scope(nullptr); | 577 set_scope(nullptr); |
577 set_info(nullptr); | 578 set_info(nullptr); |
578 return builder_.ToBytecodeArray(); | 579 return builder()->ToBytecodeArray(); |
579 } | 580 } |
580 | 581 |
581 | 582 |
582 void BytecodeGenerator::MakeBytecodeBody() { | 583 void BytecodeGenerator::MakeBytecodeBody() { |
583 // Build the arguments object if it is used. | 584 // Build the arguments object if it is used. |
584 VisitArgumentsObject(scope()->arguments()); | 585 VisitArgumentsObject(scope()->arguments()); |
585 | 586 |
586 // TODO(mythria): Build rest arguments array if it is used. | 587 // TODO(mythria): Build rest arguments array if it is used. |
587 int rest_index; | 588 int rest_index; |
588 if (scope()->rest_parameter(&rest_index)) { | 589 if (scope()->rest_parameter(&rest_index)) { |
(...skipping 1917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2506 } | 2507 } |
2507 | 2508 |
2508 | 2509 |
2509 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2510 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2510 return info()->feedback_vector()->GetIndex(slot); | 2511 return info()->feedback_vector()->GetIndex(slot); |
2511 } | 2512 } |
2512 | 2513 |
2513 } // namespace interpreter | 2514 } // namespace interpreter |
2514 } // namespace internal | 2515 } // namespace internal |
2515 } // namespace v8 | 2516 } // namespace v8 |
OLD | NEW |