| 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/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" |
| 10 #include "src/objects.h" | 11 #include "src/objects.h" |
| 11 #include "src/parsing/parser.h" | 12 #include "src/parsing/parser.h" |
| 12 #include "src/parsing/token.h" | 13 #include "src/parsing/token.h" |
| 13 | 14 |
| 14 namespace v8 { | 15 namespace v8 { |
| 15 namespace internal { | 16 namespace internal { |
| 16 namespace interpreter { | 17 namespace interpreter { |
| 17 | 18 |
| 18 | 19 |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 Statement* statement) { | 171 Statement* statement) { |
| 171 ControlScope* current = this; | 172 ControlScope* current = this; |
| 172 do { | 173 do { |
| 173 if (current->Execute(command, statement)) return; | 174 if (current->Execute(command, statement)) return; |
| 174 current = current->outer(); | 175 current = current->outer(); |
| 175 } while (current != nullptr); | 176 } while (current != nullptr); |
| 176 UNREACHABLE(); | 177 UNREACHABLE(); |
| 177 } | 178 } |
| 178 | 179 |
| 179 | 180 |
| 180 // Scoped base class for determining where the result of an expression | 181 class BytecodeGenerator::RegisterAllocationScope { |
| 181 // is stored. | |
| 182 class BytecodeGenerator::ExpressionResultScope { | |
| 183 public: | 182 public: |
| 184 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind) | 183 explicit RegisterAllocationScope(BytecodeGenerator* generator) |
| 185 : generator_(generator), | 184 : generator_(generator), |
| 186 kind_(kind), | 185 outer_(generator->register_allocator()), |
| 187 outer_(generator->execution_result()), | 186 allocator_(builder()) { |
| 188 allocator_(builder()), | 187 generator_->set_register_allocator(this); |
| 189 result_identified_(false) { | |
| 190 generator_->set_execution_result(this); | |
| 191 } | 188 } |
| 192 | 189 |
| 193 virtual ~ExpressionResultScope() { | 190 virtual ~RegisterAllocationScope() { |
| 194 generator_->set_execution_result(outer_); | 191 generator_->set_register_allocator(outer_); |
| 195 DCHECK(result_identified()); | |
| 196 } | 192 } |
| 197 | 193 |
| 198 bool IsEffect() const { return kind_ == Expression::kEffect; } | |
| 199 bool IsValue() const { return kind_ == Expression::kValue; } | |
| 200 | |
| 201 virtual void SetResultInAccumulator() = 0; | |
| 202 virtual void SetResultInRegister(Register reg) = 0; | |
| 203 | |
| 204 BytecodeGenerator* generator() const { return generator_; } | |
| 205 BytecodeArrayBuilder* builder() const { return generator()->builder(); } | |
| 206 ExpressionResultScope* outer() const { return outer_; } | |
| 207 | |
| 208 Register NewRegister() { | 194 Register NewRegister() { |
| 209 ExpressionResultScope* current_scope = generator()->execution_result(); | 195 RegisterAllocationScope* current_scope = generator()->register_allocator(); |
| 210 if ((current_scope == this) || | 196 if ((current_scope == this) || |
| 211 (current_scope->outer() == this && | 197 (current_scope->outer() == this && |
| 212 !current_scope->allocator_.hasConsecutiveAllocations())) { | 198 !current_scope->allocator_.HasConsecutiveAllocations())) { |
| 213 // Regular case - Allocating registers in current or outer context. | 199 // Regular case - Allocating registers in current or outer context. |
| 214 // VisitForRegisterValue allocates register in outer context. | 200 // VisitForRegisterValue allocates register in outer context. |
| 215 return allocator_.NewRegister(); | 201 return allocator_.NewRegister(); |
| 216 } else { | 202 } else { |
| 217 // If it is required to allocate a register other than current or outer | 203 // If it is required to allocate a register other than current or outer |
| 218 // scopes, allocate a new temporary register. It might be expensive to | 204 // scopes, allocate a new temporary register. It might be expensive to |
| 219 // walk the full context chain and compute the list of consecutive | 205 // walk the full context chain and compute the list of consecutive |
| 220 // reservations in the innerscopes. | 206 // reservations in the innerscopes. |
| 221 UNIMPLEMENTED(); | 207 UNIMPLEMENTED(); |
| 222 return Register(-1); | 208 return Register(-1); |
| 223 } | 209 } |
| 224 } | 210 } |
| 225 | 211 |
| 226 void PrepareForConsecutiveAllocations(size_t count) { | 212 void PrepareForConsecutiveAllocations(size_t count) { |
| 227 allocator_.PrepareForConsecutiveAllocations(count); | 213 allocator_.PrepareForConsecutiveAllocations(count); |
| 228 } | 214 } |
| 229 | 215 |
| 230 Register NextConsecutiveRegister() { | 216 Register NextConsecutiveRegister() { |
| 231 return allocator_.NextConsecutiveRegister(); | 217 return allocator_.NextConsecutiveRegister(); |
| 232 } | 218 } |
| 233 | 219 |
| 220 bool RegisterIsAllocatedInThisScope(Register reg) const { |
| 221 return allocator_.RegisterIsAllocatedInThisScope(reg); |
| 222 } |
| 223 |
| 224 RegisterAllocationScope* outer() const { return outer_; } |
| 225 |
| 226 private: |
| 227 BytecodeGenerator* generator() const { return generator_; } |
| 228 BytecodeArrayBuilder* builder() const { return generator_->builder(); } |
| 229 |
| 230 BytecodeGenerator* generator_; |
| 231 RegisterAllocationScope* outer_; |
| 232 BytecodeRegisterAllocator allocator_; |
| 233 |
| 234 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope); |
| 235 }; |
| 236 |
| 237 |
| 238 // Scoped base class for determining where the result of an expression |
| 239 // is stored. |
| 240 class BytecodeGenerator::ExpressionResultScope { |
| 241 public: |
| 242 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind) |
| 243 : generator_(generator), |
| 244 kind_(kind), |
| 245 outer_(generator->execution_result()), |
| 246 allocator_(generator), |
| 247 result_identified_(false) { |
| 248 generator_->set_execution_result(this); |
| 249 } |
| 250 |
| 251 virtual ~ExpressionResultScope() { |
| 252 generator_->set_execution_result(outer_); |
| 253 DCHECK(result_identified()); |
| 254 } |
| 255 |
| 256 bool IsEffect() const { return kind_ == Expression::kEffect; } |
| 257 bool IsValue() const { return kind_ == Expression::kValue; } |
| 258 |
| 259 virtual void SetResultInAccumulator() = 0; |
| 260 virtual void SetResultInRegister(Register reg) = 0; |
| 261 |
| 234 protected: | 262 protected: |
| 263 ExpressionResultScope* outer() const { return outer_; } |
| 264 BytecodeArrayBuilder* builder() const { return generator_->builder(); } |
| 265 const RegisterAllocationScope* allocator() const { return &allocator_; } |
| 266 |
| 235 void set_result_identified() { | 267 void set_result_identified() { |
| 236 DCHECK(!result_identified()); | 268 DCHECK(!result_identified()); |
| 237 result_identified_ = true; | 269 result_identified_ = true; |
| 238 } | 270 } |
| 239 | 271 |
| 240 bool result_identified() const { return result_identified_; } | 272 bool result_identified() const { return result_identified_; } |
| 241 | 273 |
| 242 const TemporaryRegisterScope* allocator() const { return &allocator_; } | |
| 243 | |
| 244 private: | 274 private: |
| 245 BytecodeGenerator* generator_; | 275 BytecodeGenerator* generator_; |
| 246 Expression::Context kind_; | 276 Expression::Context kind_; |
| 247 ExpressionResultScope* outer_; | 277 ExpressionResultScope* outer_; |
| 248 TemporaryRegisterScope allocator_; | 278 RegisterAllocationScope allocator_; |
| 249 bool result_identified_; | 279 bool result_identified_; |
| 250 | 280 |
| 251 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); | 281 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); |
| 252 }; | 282 }; |
| 253 | 283 |
| 254 | 284 |
| 255 // Scoped class used when the result of the current expression is not | 285 // Scoped class used when the result of the current expression is not |
| 256 // expected to produce a result. | 286 // expected to produce a result. |
| 257 class BytecodeGenerator::EffectResultScope final | 287 class BytecodeGenerator::EffectResultScope final |
| 258 : public ExpressionResultScope { | 288 : public ExpressionResultScope { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 286 | 316 |
| 287 // Scoped class used when the result of the current expression to be | 317 // Scoped class used when the result of the current expression to be |
| 288 // evaluated should go into an interpreter register. | 318 // evaluated should go into an interpreter register. |
| 289 class BytecodeGenerator::RegisterResultScope final | 319 class BytecodeGenerator::RegisterResultScope final |
| 290 : public ExpressionResultScope { | 320 : public ExpressionResultScope { |
| 291 public: | 321 public: |
| 292 explicit RegisterResultScope(BytecodeGenerator* generator) | 322 explicit RegisterResultScope(BytecodeGenerator* generator) |
| 293 : ExpressionResultScope(generator, Expression::kValue) {} | 323 : ExpressionResultScope(generator, Expression::kValue) {} |
| 294 | 324 |
| 295 virtual void SetResultInAccumulator() { | 325 virtual void SetResultInAccumulator() { |
| 296 result_register_ = outer()->NewRegister(); | 326 result_register_ = allocator()->outer()->NewRegister(); |
| 297 builder()->StoreAccumulatorInRegister(result_register_); | 327 builder()->StoreAccumulatorInRegister(result_register_); |
| 298 set_result_identified(); | 328 set_result_identified(); |
| 299 } | 329 } |
| 300 | 330 |
| 301 virtual void SetResultInRegister(Register reg) { | 331 virtual void SetResultInRegister(Register reg) { |
| 302 DCHECK(builder()->RegisterIsParameterOrLocal(reg) || | 332 DCHECK(builder()->RegisterIsParameterOrLocal(reg) || |
| 303 (builder()->RegisterIsTemporary(reg) && | 333 (builder()->RegisterIsTemporary(reg) && |
| 304 !allocator()->RegisterIsAllocatedInThisScope(reg))); | 334 !allocator()->RegisterIsAllocatedInThisScope(reg))); |
| 305 result_register_ = reg; | 335 result_register_ = reg; |
| 306 set_result_identified(); | 336 set_result_identified(); |
| 307 } | 337 } |
| 308 | 338 |
| 309 Register ResultRegister() const { return result_register_; } | 339 Register ResultRegister() const { return result_register_; } |
| 310 | 340 |
| 311 private: | 341 private: |
| 312 Register result_register_; | 342 Register result_register_; |
| 313 }; | 343 }; |
| 314 | 344 |
| 315 | 345 |
| 316 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) | 346 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) |
| 317 : isolate_(isolate), | 347 : isolate_(isolate), |
| 318 zone_(zone), | 348 zone_(zone), |
| 319 builder_(isolate, zone), | 349 builder_(isolate, zone), |
| 320 info_(nullptr), | 350 info_(nullptr), |
| 321 scope_(nullptr), | 351 scope_(nullptr), |
| 322 globals_(0, zone), | 352 globals_(0, zone), |
| 323 execution_control_(nullptr), | 353 execution_control_(nullptr), |
| 324 execution_context_(nullptr), | 354 execution_context_(nullptr), |
| 325 execution_result_(nullptr) { | 355 execution_result_(nullptr), |
| 356 register_allocator_(nullptr) { |
| 326 InitializeAstVisitor(isolate); | 357 InitializeAstVisitor(isolate); |
| 327 } | 358 } |
| 328 | 359 |
| 329 | 360 |
| 330 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { | 361 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { |
| 331 set_info(info); | 362 set_info(info); |
| 332 set_scope(info->scope()); | 363 set_scope(info->scope()); |
| 333 | 364 |
| 334 // Initialize the incoming context. | 365 // Initialize the incoming context. |
| 335 ContextScope incoming_context(this, scope(), false); | 366 ContextScope incoming_context(this, scope(), false); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 } | 524 } |
| 494 | 525 |
| 495 | 526 |
| 496 void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) { | 527 void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) { |
| 497 UNIMPLEMENTED(); | 528 UNIMPLEMENTED(); |
| 498 } | 529 } |
| 499 | 530 |
| 500 | 531 |
| 501 void BytecodeGenerator::VisitDeclarations( | 532 void BytecodeGenerator::VisitDeclarations( |
| 502 ZoneList<Declaration*>* declarations) { | 533 ZoneList<Declaration*>* declarations) { |
| 534 RegisterAllocationScope register_scope(this); |
| 503 DCHECK(globals()->empty()); | 535 DCHECK(globals()->empty()); |
| 504 AstVisitor::VisitDeclarations(declarations); | 536 AstVisitor::VisitDeclarations(declarations); |
| 505 if (globals()->empty()) return; | 537 if (globals()->empty()) return; |
| 506 int array_index = 0; | 538 int array_index = 0; |
| 507 Handle<FixedArray> data = isolate()->factory()->NewFixedArray( | 539 Handle<FixedArray> data = isolate()->factory()->NewFixedArray( |
| 508 static_cast<int>(globals()->size()), TENURED); | 540 static_cast<int>(globals()->size()), TENURED); |
| 509 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj); | 541 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj); |
| 510 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | | 542 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | |
| 511 DeclareGlobalsNativeFlag::encode(info()->is_native()) | | 543 DeclareGlobalsNativeFlag::encode(info()->is_native()) | |
| 512 DeclareGlobalsLanguageMode::encode(language_mode()); | 544 DeclareGlobalsLanguageMode::encode(language_mode()); |
| 513 | 545 |
| 514 TemporaryRegisterScope temporary_register_scope(builder()); | 546 Register pairs = register_allocator()->NewRegister(); |
| 515 Register pairs = temporary_register_scope.NewRegister(); | |
| 516 builder()->LoadLiteral(data); | 547 builder()->LoadLiteral(data); |
| 517 builder()->StoreAccumulatorInRegister(pairs); | 548 builder()->StoreAccumulatorInRegister(pairs); |
| 518 | 549 |
| 519 Register flags = temporary_register_scope.NewRegister(); | 550 Register flags = register_allocator()->NewRegister(); |
| 520 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); | 551 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); |
| 521 builder()->StoreAccumulatorInRegister(flags); | 552 builder()->StoreAccumulatorInRegister(flags); |
| 522 DCHECK(flags.index() == pairs.index() + 1); | 553 DCHECK(flags.index() == pairs.index() + 1); |
| 523 | 554 |
| 524 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); | 555 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); |
| 525 globals()->clear(); | 556 globals()->clear(); |
| 526 } | 557 } |
| 527 | 558 |
| 528 | 559 |
| 560 void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { |
| 561 for (int i = 0; i < statements->length(); i++) { |
| 562 // Allocate an outer register allocations scope for the statement. |
| 563 RegisterAllocationScope allocation_scope(this); |
| 564 Statement* stmt = statements->at(i); |
| 565 Visit(stmt); |
| 566 if (stmt->IsJump()) break; |
| 567 } |
| 568 } |
| 569 |
| 570 |
| 529 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 571 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 530 EffectResultScope statement_result_scope(this); | |
| 531 VisitForEffect(stmt->expression()); | 572 VisitForEffect(stmt->expression()); |
| 532 } | 573 } |
| 533 | 574 |
| 534 | 575 |
| 535 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 576 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
| 536 } | 577 } |
| 537 | 578 |
| 538 | 579 |
| 539 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { | 580 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { |
| 540 BytecodeLabel else_label, end_label; | 581 BytecodeLabel else_label, end_label; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 575 execution_control()->Continue(stmt->target()); | 616 execution_control()->Continue(stmt->target()); |
| 576 } | 617 } |
| 577 | 618 |
| 578 | 619 |
| 579 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 620 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
| 580 execution_control()->Break(stmt->target()); | 621 execution_control()->Break(stmt->target()); |
| 581 } | 622 } |
| 582 | 623 |
| 583 | 624 |
| 584 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 625 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
| 585 EffectResultScope statement_result_scope(this); | |
| 586 VisitForAccumulatorValue(stmt->expression()); | 626 VisitForAccumulatorValue(stmt->expression()); |
| 587 builder()->Return(); | 627 builder()->Return(); |
| 588 } | 628 } |
| 589 | 629 |
| 590 | 630 |
| 591 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 631 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
| 592 UNIMPLEMENTED(); | 632 UNIMPLEMENTED(); |
| 593 } | 633 } |
| 594 | 634 |
| 595 | 635 |
| 596 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 636 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 597 // We need this scope because we visit for register values. We have to | 637 // We need this scope because we visit for register values. We have to |
| 598 // maintain a execution result scope where registers can be allocated. | 638 // maintain a execution result scope where registers can be allocated. |
| 599 EffectResultScope effect_results_scope(this); | |
| 600 ZoneList<CaseClause*>* clauses = stmt->cases(); | 639 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 601 SwitchBuilder switch_builder(builder(), clauses->length()); | 640 SwitchBuilder switch_builder(builder(), clauses->length()); |
| 602 ControlScopeForBreakable scope(this, stmt, &switch_builder); | 641 ControlScopeForBreakable scope(this, stmt, &switch_builder); |
| 603 int default_index = -1; | 642 int default_index = -1; |
| 604 | 643 |
| 605 // Keep the switch value in a register until a case matches. | 644 // Keep the switch value in a register until a case matches. |
| 606 Register tag = VisitForRegisterValue(stmt->tag()); | 645 Register tag = VisitForRegisterValue(stmt->tag()); |
| 607 | 646 |
| 608 // Iterate over all cases and create nodes for label comparison. | 647 // Iterate over all cases and create nodes for label comparison. |
| 609 BytecodeLabel done_label; | 648 BytecodeLabel done_label; |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 // accumulator. | 767 // accumulator. |
| 729 Property* property = expr->AsProperty(); | 768 Property* property = expr->AsProperty(); |
| 730 LhsKind assign_type = Property::GetAssignType(property); | 769 LhsKind assign_type = Property::GetAssignType(property); |
| 731 switch (assign_type) { | 770 switch (assign_type) { |
| 732 case VARIABLE: { | 771 case VARIABLE: { |
| 733 Variable* variable = expr->AsVariableProxy()->var(); | 772 Variable* variable = expr->AsVariableProxy()->var(); |
| 734 VisitVariableAssignment(variable, slot); | 773 VisitVariableAssignment(variable, slot); |
| 735 break; | 774 break; |
| 736 } | 775 } |
| 737 case NAMED_PROPERTY: { | 776 case NAMED_PROPERTY: { |
| 738 TemporaryRegisterScope temporary_register_scope(builder()); | 777 RegisterAllocationScope register_scope(this); |
| 739 Register value = temporary_register_scope.NewRegister(); | 778 Register value = register_allocator()->NewRegister(); |
| 740 builder()->StoreAccumulatorInRegister(value); | 779 builder()->StoreAccumulatorInRegister(value); |
| 741 Register object = VisitForRegisterValue(property->obj()); | 780 Register object = VisitForRegisterValue(property->obj()); |
| 742 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); | 781 Handle<String> name = property->key()->AsLiteral()->AsPropertyName(); |
| 743 builder()->LoadAccumulatorWithRegister(value); | 782 builder()->LoadAccumulatorWithRegister(value); |
| 744 builder()->StoreNamedProperty(object, name, feedback_index(slot), | 783 builder()->StoreNamedProperty(object, name, feedback_index(slot), |
| 745 language_mode()); | 784 language_mode()); |
| 746 break; | 785 break; |
| 747 } | 786 } |
| 748 case KEYED_PROPERTY: { | 787 case KEYED_PROPERTY: { |
| 749 TemporaryRegisterScope temporary_register_scope(builder()); | 788 RegisterAllocationScope register_scope(this); |
| 750 Register value = temporary_register_scope.NewRegister(); | 789 Register value = register_allocator()->NewRegister(); |
| 751 builder()->StoreAccumulatorInRegister(value); | 790 builder()->StoreAccumulatorInRegister(value); |
| 752 Register object = VisitForRegisterValue(property->obj()); | 791 Register object = VisitForRegisterValue(property->obj()); |
| 753 Register key = VisitForRegisterValue(property->key()); | 792 Register key = VisitForRegisterValue(property->key()); |
| 754 builder()->LoadAccumulatorWithRegister(value); | 793 builder()->LoadAccumulatorWithRegister(value); |
| 755 builder()->StoreKeyedProperty(object, key, feedback_index(slot), | 794 builder()->StoreKeyedProperty(object, key, feedback_index(slot), |
| 756 language_mode()); | 795 language_mode()); |
| 757 break; | 796 break; |
| 758 } | 797 } |
| 759 case NAMED_SUPER_PROPERTY: | 798 case NAMED_SUPER_PROPERTY: |
| 760 case KEYED_SUPER_PROPERTY: | 799 case KEYED_SUPER_PROPERTY: |
| 761 UNIMPLEMENTED(); | 800 UNIMPLEMENTED(); |
| 762 } | 801 } |
| 763 } | 802 } |
| 764 | 803 |
| 765 | 804 |
| 766 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 805 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 767 EffectResultScope statement_result_scope(this); | |
| 768 if (stmt->subject()->IsNullLiteral() || | 806 if (stmt->subject()->IsNullLiteral() || |
| 769 stmt->subject()->IsUndefinedLiteral(isolate())) { | 807 stmt->subject()->IsUndefinedLiteral(isolate())) { |
| 770 // ForIn generates lots of code, skip if it wouldn't produce any effects. | 808 // ForIn generates lots of code, skip if it wouldn't produce any effects. |
| 771 return; | 809 return; |
| 772 } | 810 } |
| 773 | 811 |
| 774 LoopBuilder loop_builder(builder()); | 812 LoopBuilder loop_builder(builder()); |
| 775 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | 813 ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
| 776 BytecodeLabel subject_null_label, subject_undefined_label, not_object_label; | 814 BytecodeLabel subject_null_label, subject_undefined_label, not_object_label; |
| 777 | 815 |
| 778 // Prepare the state for executing ForIn. | 816 // Prepare the state for executing ForIn. |
| 779 VisitForAccumulatorValue(stmt->subject()); | 817 VisitForAccumulatorValue(stmt->subject()); |
| 780 builder()->JumpIfUndefined(&subject_undefined_label); | 818 builder()->JumpIfUndefined(&subject_undefined_label); |
| 781 builder()->JumpIfNull(&subject_null_label); | 819 builder()->JumpIfNull(&subject_null_label); |
| 782 Register receiver = execution_result()->NewRegister(); | 820 Register receiver = register_allocator()->NewRegister(); |
| 783 builder()->CastAccumulatorToJSObject(); | 821 builder()->CastAccumulatorToJSObject(); |
| 784 builder()->JumpIfNull(¬_object_label); | 822 builder()->JumpIfNull(¬_object_label); |
| 785 builder()->StoreAccumulatorInRegister(receiver); | 823 builder()->StoreAccumulatorInRegister(receiver); |
| 786 Register cache_type = execution_result()->NewRegister(); | 824 Register cache_type = register_allocator()->NewRegister(); |
| 787 Register cache_array = execution_result()->NewRegister(); | 825 Register cache_array = register_allocator()->NewRegister(); |
| 788 Register cache_length = execution_result()->NewRegister(); | 826 Register cache_length = register_allocator()->NewRegister(); |
| 789 builder()->ForInPrepare(cache_type, cache_array, cache_length); | 827 builder()->ForInPrepare(cache_type, cache_array, cache_length); |
| 790 | 828 |
| 791 // Set up loop counter | 829 // Set up loop counter |
| 792 Register index = execution_result()->NewRegister(); | 830 Register index = register_allocator()->NewRegister(); |
| 793 builder()->LoadLiteral(Smi::FromInt(0)); | 831 builder()->LoadLiteral(Smi::FromInt(0)); |
| 794 builder()->StoreAccumulatorInRegister(index); | 832 builder()->StoreAccumulatorInRegister(index); |
| 795 | 833 |
| 796 // The loop | 834 // The loop |
| 797 loop_builder.LoopHeader(); | 835 loop_builder.LoopHeader(); |
| 798 loop_builder.Condition(); | 836 loop_builder.Condition(); |
| 799 builder()->ForInDone(index, cache_length); | 837 builder()->ForInDone(index, cache_length); |
| 800 loop_builder.BreakIfTrue(); | 838 loop_builder.BreakIfTrue(); |
| 801 builder()->ForInNext(receiver, cache_type, cache_array, index); | 839 builder()->ForInNext(receiver, cache_type, cache_array, index); |
| 802 loop_builder.ContinueIfUndefined(); | 840 loop_builder.ContinueIfUndefined(); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 } else { | 946 } else { |
| 909 builder()->LoadLiteral(value); | 947 builder()->LoadLiteral(value); |
| 910 } | 948 } |
| 911 execution_result()->SetResultInAccumulator(); | 949 execution_result()->SetResultInAccumulator(); |
| 912 } | 950 } |
| 913 } | 951 } |
| 914 | 952 |
| 915 | 953 |
| 916 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 954 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 917 // Materialize a regular expression literal. | 955 // Materialize a regular expression literal. |
| 918 TemporaryRegisterScope temporary_register_scope(builder()); | |
| 919 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(), | 956 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(), |
| 920 expr->flags()); | 957 expr->flags()); |
| 921 execution_result()->SetResultInAccumulator(); | 958 execution_result()->SetResultInAccumulator(); |
| 922 } | 959 } |
| 923 | 960 |
| 924 | 961 |
| 925 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 962 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 926 // Deep-copy the literal boilerplate. | 963 // Deep-copy the literal boilerplate. |
| 927 builder()->CreateObjectLiteral(expr->constant_properties(), | 964 builder()->CreateObjectLiteral(expr->constant_properties(), |
| 928 expr->literal_index(), | 965 expr->literal_index(), |
| 929 expr->ComputeFlags(true)); | 966 expr->ComputeFlags(true)); |
| 930 | |
| 931 TemporaryRegisterScope temporary_register_scope(builder()); | |
| 932 Register literal; | 967 Register literal; |
| 933 | 968 |
| 934 // Store computed values into the literal. | 969 // Store computed values into the literal. |
| 935 bool literal_in_accumulator = true; | 970 bool literal_in_accumulator = true; |
| 936 int property_index = 0; | 971 int property_index = 0; |
| 937 AccessorTable accessor_table(zone()); | 972 AccessorTable accessor_table(zone()); |
| 938 for (; property_index < expr->properties()->length(); property_index++) { | 973 for (; property_index < expr->properties()->length(); property_index++) { |
| 939 TemporaryRegisterScope inner_temporary_register_scope(builder()); | |
| 940 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 974 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 941 if (property->is_computed_name()) break; | 975 if (property->is_computed_name()) break; |
| 942 if (property->IsCompileTimeValue()) continue; | 976 if (property->IsCompileTimeValue()) continue; |
| 943 | 977 |
| 944 if (literal_in_accumulator) { | 978 if (literal_in_accumulator) { |
| 945 literal = temporary_register_scope.NewRegister(); | 979 literal = register_allocator()->NewRegister(); |
| 946 builder()->StoreAccumulatorInRegister(literal); | 980 builder()->StoreAccumulatorInRegister(literal); |
| 947 literal_in_accumulator = false; | 981 literal_in_accumulator = false; |
| 948 } | 982 } |
| 949 | 983 |
| 984 RegisterAllocationScope inner_register_scope(this); |
| 950 Literal* literal_key = property->key()->AsLiteral(); | 985 Literal* literal_key = property->key()->AsLiteral(); |
| 951 switch (property->kind()) { | 986 switch (property->kind()) { |
| 952 case ObjectLiteral::Property::CONSTANT: | 987 case ObjectLiteral::Property::CONSTANT: |
| 953 UNREACHABLE(); | 988 UNREACHABLE(); |
| 954 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 989 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 955 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); | 990 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value())); |
| 956 // Fall through. | 991 // Fall through. |
| 957 case ObjectLiteral::Property::COMPUTED: { | 992 case ObjectLiteral::Property::COMPUTED: { |
| 958 // It is safe to use [[Put]] here because the boilerplate already | 993 // It is safe to use [[Put]] here because the boilerplate already |
| 959 // contains computed properties with an uninitialized value. | 994 // contains computed properties with an uninitialized value. |
| 960 if (literal_key->value()->IsInternalizedString()) { | 995 if (literal_key->value()->IsInternalizedString()) { |
| 961 if (property->emit_store()) { | 996 if (property->emit_store()) { |
| 962 VisitForAccumulatorValue(property->value()); | 997 VisitForAccumulatorValue(property->value()); |
| 963 builder()->StoreNamedProperty( | 998 builder()->StoreNamedProperty( |
| 964 literal, literal_key->AsPropertyName(), | 999 literal, literal_key->AsPropertyName(), |
| 965 feedback_index(property->GetSlot(0)), language_mode()); | 1000 feedback_index(property->GetSlot(0)), language_mode()); |
| 966 } else { | 1001 } else { |
| 967 VisitForEffect(property->value()); | 1002 VisitForEffect(property->value()); |
| 968 } | 1003 } |
| 969 } else { | 1004 } else { |
| 970 inner_temporary_register_scope.PrepareForConsecutiveAllocations(3); | 1005 register_allocator()->PrepareForConsecutiveAllocations(3); |
| 971 Register key = | 1006 Register key = register_allocator()->NextConsecutiveRegister(); |
| 972 inner_temporary_register_scope.NextConsecutiveRegister(); | 1007 Register value = register_allocator()->NextConsecutiveRegister(); |
| 973 Register value = | 1008 Register language = register_allocator()->NextConsecutiveRegister(); |
| 974 inner_temporary_register_scope.NextConsecutiveRegister(); | |
| 975 Register language = | |
| 976 inner_temporary_register_scope.NextConsecutiveRegister(); | |
| 977 // TODO(oth): This is problematic - can't assume contiguous here. | 1009 // TODO(oth): This is problematic - can't assume contiguous here. |
| 978 // literal is allocated in temporary_register_scope, whereas | 1010 // literal is allocated in outer register scope, whereas key, value, |
| 979 // key, value, language are in another. | 1011 // language are in another. |
| 980 DCHECK(Register::AreContiguous(literal, key, value, language)); | 1012 DCHECK(Register::AreContiguous(literal, key, value, language)); |
| 981 VisitForAccumulatorValue(property->key()); | 1013 VisitForAccumulatorValue(property->key()); |
| 982 builder()->StoreAccumulatorInRegister(key); | 1014 builder()->StoreAccumulatorInRegister(key); |
| 983 VisitForAccumulatorValue(property->value()); | 1015 VisitForAccumulatorValue(property->value()); |
| 984 builder()->StoreAccumulatorInRegister(value); | 1016 builder()->StoreAccumulatorInRegister(value); |
| 985 if (property->emit_store()) { | 1017 if (property->emit_store()) { |
| 986 builder() | 1018 builder() |
| 987 ->LoadLiteral(Smi::FromInt(SLOPPY)) | 1019 ->LoadLiteral(Smi::FromInt(SLOPPY)) |
| 988 .StoreAccumulatorInRegister(language) | 1020 .StoreAccumulatorInRegister(language) |
| 989 .CallRuntime(Runtime::kSetProperty, literal, 4); | 1021 .CallRuntime(Runtime::kSetProperty, literal, 4); |
| 990 VisitSetHomeObject(value, literal, property); | 1022 VisitSetHomeObject(value, literal, property); |
| 991 } | 1023 } |
| 992 } | 1024 } |
| 993 break; | 1025 break; |
| 994 } | 1026 } |
| 995 case ObjectLiteral::Property::PROTOTYPE: { | 1027 case ObjectLiteral::Property::PROTOTYPE: { |
| 996 inner_temporary_register_scope.PrepareForConsecutiveAllocations(1); | 1028 register_allocator()->PrepareForConsecutiveAllocations(1); |
| 997 DCHECK(property->emit_store()); | 1029 DCHECK(property->emit_store()); |
| 998 Register value = | 1030 Register value = register_allocator()->NextConsecutiveRegister(); |
| 999 inner_temporary_register_scope.NextConsecutiveRegister(); | |
| 1000 DCHECK(Register::AreContiguous(literal, value)); | 1031 DCHECK(Register::AreContiguous(literal, value)); |
| 1001 VisitForAccumulatorValue(property->value()); | 1032 VisitForAccumulatorValue(property->value()); |
| 1002 builder()->StoreAccumulatorInRegister(value).CallRuntime( | 1033 builder()->StoreAccumulatorInRegister(value).CallRuntime( |
| 1003 Runtime::kInternalSetPrototype, literal, 2); | 1034 Runtime::kInternalSetPrototype, literal, 2); |
| 1004 break; | 1035 break; |
| 1005 } | 1036 } |
| 1006 case ObjectLiteral::Property::GETTER: | 1037 case ObjectLiteral::Property::GETTER: |
| 1007 if (property->emit_store()) { | 1038 if (property->emit_store()) { |
| 1008 accessor_table.lookup(literal_key)->second->getter = property; | 1039 accessor_table.lookup(literal_key)->second->getter = property; |
| 1009 } | 1040 } |
| 1010 break; | 1041 break; |
| 1011 case ObjectLiteral::Property::SETTER: | 1042 case ObjectLiteral::Property::SETTER: |
| 1012 if (property->emit_store()) { | 1043 if (property->emit_store()) { |
| 1013 accessor_table.lookup(literal_key)->second->setter = property; | 1044 accessor_table.lookup(literal_key)->second->setter = property; |
| 1014 } | 1045 } |
| 1015 break; | 1046 break; |
| 1016 } | 1047 } |
| 1017 } | 1048 } |
| 1018 | 1049 |
| 1019 // Define accessors, using only a single call to the runtime for each pair of | 1050 // Define accessors, using only a single call to the runtime for each pair of |
| 1020 // corresponding getters and setters. | 1051 // corresponding getters and setters. |
| 1021 for (AccessorTable::Iterator it = accessor_table.begin(); | 1052 for (AccessorTable::Iterator it = accessor_table.begin(); |
| 1022 it != accessor_table.end(); ++it) { | 1053 it != accessor_table.end(); ++it) { |
| 1023 TemporaryRegisterScope inner_temporary_register_scope(builder()); | 1054 RegisterAllocationScope inner_register_scope(this); |
| 1024 inner_temporary_register_scope.PrepareForConsecutiveAllocations(4); | 1055 register_allocator()->PrepareForConsecutiveAllocations(4); |
| 1025 Register name = inner_temporary_register_scope.NextConsecutiveRegister(); | 1056 Register name = register_allocator()->NextConsecutiveRegister(); |
| 1026 Register getter = inner_temporary_register_scope.NextConsecutiveRegister(); | 1057 Register getter = register_allocator()->NextConsecutiveRegister(); |
| 1027 Register setter = inner_temporary_register_scope.NextConsecutiveRegister(); | 1058 Register setter = register_allocator()->NextConsecutiveRegister(); |
| 1028 Register attr = inner_temporary_register_scope.NextConsecutiveRegister(); | 1059 Register attr = register_allocator()->NextConsecutiveRegister(); |
| 1029 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); | 1060 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); |
| 1030 VisitForAccumulatorValue(it->first); | 1061 VisitForAccumulatorValue(it->first); |
| 1031 builder()->StoreAccumulatorInRegister(name); | 1062 builder()->StoreAccumulatorInRegister(name); |
| 1032 VisitObjectLiteralAccessor(literal, it->second->getter, getter); | 1063 VisitObjectLiteralAccessor(literal, it->second->getter, getter); |
| 1033 VisitObjectLiteralAccessor(literal, it->second->setter, setter); | 1064 VisitObjectLiteralAccessor(literal, it->second->setter, setter); |
| 1034 builder() | 1065 builder() |
| 1035 ->LoadLiteral(Smi::FromInt(NONE)) | 1066 ->LoadLiteral(Smi::FromInt(NONE)) |
| 1036 .StoreAccumulatorInRegister(attr) | 1067 .StoreAccumulatorInRegister(attr) |
| 1037 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5); | 1068 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5); |
| 1038 } | 1069 } |
| 1039 | 1070 |
| 1040 // Object literals have two parts. The "static" part on the left contains no | 1071 // Object literals have two parts. The "static" part on the left contains no |
| 1041 // computed property names, and so we can compute its map ahead of time; see | 1072 // computed property names, and so we can compute its map ahead of time; see |
| 1042 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts | 1073 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts |
| 1043 // with the first computed property name and continues with all properties to | 1074 // with the first computed property name and continues with all properties to |
| 1044 // its right. All the code from above initializes the static component of the | 1075 // its right. All the code from above initializes the static component of the |
| 1045 // object literal, and arranges for the map of the result to reflect the | 1076 // object literal, and arranges for the map of the result to reflect the |
| 1046 // static order in which the keys appear. For the dynamic properties, we | 1077 // static order in which the keys appear. For the dynamic properties, we |
| 1047 // compile them into a series of "SetOwnProperty" runtime calls. This will | 1078 // compile them into a series of "SetOwnProperty" runtime calls. This will |
| 1048 // preserve insertion order. | 1079 // preserve insertion order. |
| 1049 for (; property_index < expr->properties()->length(); property_index++) { | 1080 for (; property_index < expr->properties()->length(); property_index++) { |
| 1050 ObjectLiteral::Property* property = expr->properties()->at(property_index); | |
| 1051 | |
| 1052 if (literal_in_accumulator) { | 1081 if (literal_in_accumulator) { |
| 1053 temporary_register_scope.PrepareForConsecutiveAllocations(4); | 1082 literal = register_allocator()->NewRegister(); |
| 1054 literal = temporary_register_scope.NextConsecutiveRegister(); | |
| 1055 builder()->StoreAccumulatorInRegister(literal); | 1083 builder()->StoreAccumulatorInRegister(literal); |
| 1056 literal_in_accumulator = false; | 1084 literal_in_accumulator = false; |
| 1057 } | 1085 } |
| 1058 | 1086 |
| 1087 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
| 1088 RegisterAllocationScope inner_register_scope(this); |
| 1059 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 1089 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
| 1060 DCHECK(property->emit_store()); | 1090 DCHECK(property->emit_store()); |
| 1061 TemporaryRegisterScope inner_temporary_register_scope(builder()); | 1091 Register value = register_allocator()->NewRegister(); |
| 1062 Register value = inner_temporary_register_scope.NewRegister(); | |
| 1063 DCHECK(Register::AreContiguous(literal, value)); | 1092 DCHECK(Register::AreContiguous(literal, value)); |
| 1064 VisitForAccumulatorValue(property->value()); | 1093 VisitForAccumulatorValue(property->value()); |
| 1065 builder()->StoreAccumulatorInRegister(value).CallRuntime( | 1094 builder()->StoreAccumulatorInRegister(value).CallRuntime( |
| 1066 Runtime::kInternalSetPrototype, literal, 2); | 1095 Runtime::kInternalSetPrototype, literal, 2); |
| 1067 continue; | 1096 continue; |
| 1068 } | 1097 } |
| 1069 | 1098 |
| 1070 TemporaryRegisterScope inner_temporary_register_scope(builder()); | 1099 register_allocator()->PrepareForConsecutiveAllocations(3); |
| 1071 inner_temporary_register_scope.PrepareForConsecutiveAllocations(3); | 1100 Register key = register_allocator()->NextConsecutiveRegister(); |
| 1072 Register key = inner_temporary_register_scope.NextConsecutiveRegister(); | 1101 Register value = register_allocator()->NextConsecutiveRegister(); |
| 1073 Register value = inner_temporary_register_scope.NextConsecutiveRegister(); | 1102 Register attr = register_allocator()->NextConsecutiveRegister(); |
| 1074 Register attr = inner_temporary_register_scope.NextConsecutiveRegister(); | |
| 1075 DCHECK(Register::AreContiguous(literal, key, value, attr)); | 1103 DCHECK(Register::AreContiguous(literal, key, value, attr)); |
| 1076 | 1104 |
| 1077 VisitForAccumulatorValue(property->key()); | 1105 VisitForAccumulatorValue(property->key()); |
| 1078 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); | 1106 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); |
| 1079 VisitForAccumulatorValue(property->value()); | 1107 VisitForAccumulatorValue(property->value()); |
| 1080 builder()->StoreAccumulatorInRegister(value); | 1108 builder()->StoreAccumulatorInRegister(value); |
| 1081 VisitSetHomeObject(value, literal, property); | 1109 VisitSetHomeObject(value, literal, property); |
| 1082 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); | 1110 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); |
| 1083 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1); | 1111 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1); |
| 1084 switch (property->kind()) { | 1112 switch (property->kind()) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1112 } | 1140 } |
| 1113 execution_result()->SetResultInAccumulator(); | 1141 execution_result()->SetResultInAccumulator(); |
| 1114 } | 1142 } |
| 1115 | 1143 |
| 1116 | 1144 |
| 1117 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1145 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 1118 // Deep-copy the literal boilerplate. | 1146 // Deep-copy the literal boilerplate. |
| 1119 builder()->CreateArrayLiteral(expr->constant_elements(), | 1147 builder()->CreateArrayLiteral(expr->constant_elements(), |
| 1120 expr->literal_index(), | 1148 expr->literal_index(), |
| 1121 expr->ComputeFlags(true)); | 1149 expr->ComputeFlags(true)); |
| 1122 | |
| 1123 TemporaryRegisterScope temporary_register_scope(builder()); | |
| 1124 Register index, literal; | 1150 Register index, literal; |
| 1125 | 1151 |
| 1126 // Evaluate all the non-constant subexpressions and store them into the | 1152 // Evaluate all the non-constant subexpressions and store them into the |
| 1127 // newly cloned array. | 1153 // newly cloned array. |
| 1128 bool literal_in_accumulator = true; | 1154 bool literal_in_accumulator = true; |
| 1129 for (int array_index = 0; array_index < expr->values()->length(); | 1155 for (int array_index = 0; array_index < expr->values()->length(); |
| 1130 array_index++) { | 1156 array_index++) { |
| 1131 Expression* subexpr = expr->values()->at(array_index); | 1157 Expression* subexpr = expr->values()->at(array_index); |
| 1132 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 1158 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| 1133 if (subexpr->IsSpread()) { | 1159 if (subexpr->IsSpread()) { |
| 1134 // TODO(rmcilroy): Deal with spread expressions. | 1160 // TODO(rmcilroy): Deal with spread expressions. |
| 1135 UNIMPLEMENTED(); | 1161 UNIMPLEMENTED(); |
| 1136 } | 1162 } |
| 1137 | 1163 |
| 1138 if (literal_in_accumulator) { | 1164 if (literal_in_accumulator) { |
| 1139 index = temporary_register_scope.NewRegister(); | 1165 index = register_allocator()->NewRegister(); |
| 1140 literal = temporary_register_scope.NewRegister(); | 1166 literal = register_allocator()->NewRegister(); |
| 1141 builder()->StoreAccumulatorInRegister(literal); | 1167 builder()->StoreAccumulatorInRegister(literal); |
| 1142 literal_in_accumulator = false; | 1168 literal_in_accumulator = false; |
| 1143 } | 1169 } |
| 1144 | 1170 |
| 1145 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot(); | 1171 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot(); |
| 1146 builder() | 1172 builder() |
| 1147 ->LoadLiteral(Smi::FromInt(array_index)) | 1173 ->LoadLiteral(Smi::FromInt(array_index)) |
| 1148 .StoreAccumulatorInRegister(index); | 1174 .StoreAccumulatorInRegister(index); |
| 1149 VisitForAccumulatorValue(subexpr); | 1175 VisitForAccumulatorValue(subexpr); |
| 1150 builder()->StoreKeyedProperty(literal, index, feedback_index(slot), | 1176 builder()->StoreKeyedProperty(literal, index, feedback_index(slot), |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1189 execution_result()->SetResultInAccumulator(); | 1215 execution_result()->SetResultInAccumulator(); |
| 1190 break; | 1216 break; |
| 1191 } | 1217 } |
| 1192 case VariableLocation::CONTEXT: { | 1218 case VariableLocation::CONTEXT: { |
| 1193 int depth = execution_context()->ContextChainDepth(variable->scope()); | 1219 int depth = execution_context()->ContextChainDepth(variable->scope()); |
| 1194 ContextScope* context = execution_context()->Previous(depth); | 1220 ContextScope* context = execution_context()->Previous(depth); |
| 1195 Register context_reg; | 1221 Register context_reg; |
| 1196 if (context) { | 1222 if (context) { |
| 1197 context_reg = context->reg(); | 1223 context_reg = context->reg(); |
| 1198 } else { | 1224 } else { |
| 1199 context_reg = execution_result()->NewRegister(); | 1225 context_reg = register_allocator()->NewRegister(); |
| 1200 // Walk the context chain to find the context at the given depth. | 1226 // Walk the context chain to find the context at the given depth. |
| 1201 // TODO(rmcilroy): Perform this work in a bytecode handler once we have | 1227 // TODO(rmcilroy): Perform this work in a bytecode handler once we have |
| 1202 // a generic mechanism for performing jumps in interpreter.cc. | 1228 // a generic mechanism for performing jumps in interpreter.cc. |
| 1203 // TODO(mythria): Also update bytecode graph builder with correct depth | 1229 // TODO(mythria): Also update bytecode graph builder with correct depth |
| 1204 // when this changes. | 1230 // when this changes. |
| 1205 builder() | 1231 builder() |
| 1206 ->LoadAccumulatorWithRegister(execution_context()->reg()) | 1232 ->LoadAccumulatorWithRegister(execution_context()->reg()) |
| 1207 .StoreAccumulatorInRegister(context_reg); | 1233 .StoreAccumulatorInRegister(context_reg); |
| 1208 for (int i = 0; i < depth; ++i) { | 1234 for (int i = 0; i < depth; ++i) { |
| 1209 builder() | 1235 builder() |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1264 break; | 1290 break; |
| 1265 } | 1291 } |
| 1266 case VariableLocation::CONTEXT: { | 1292 case VariableLocation::CONTEXT: { |
| 1267 // TODO(rmcilroy): support const mode initialization. | 1293 // TODO(rmcilroy): support const mode initialization. |
| 1268 int depth = execution_context()->ContextChainDepth(variable->scope()); | 1294 int depth = execution_context()->ContextChainDepth(variable->scope()); |
| 1269 ContextScope* context = execution_context()->Previous(depth); | 1295 ContextScope* context = execution_context()->Previous(depth); |
| 1270 Register context_reg; | 1296 Register context_reg; |
| 1271 if (context) { | 1297 if (context) { |
| 1272 context_reg = context->reg(); | 1298 context_reg = context->reg(); |
| 1273 } else { | 1299 } else { |
| 1274 Register value_temp = execution_result()->NewRegister(); | 1300 Register value_temp = register_allocator()->NewRegister(); |
| 1275 context_reg = execution_result()->NewRegister(); | 1301 context_reg = register_allocator()->NewRegister(); |
| 1276 // Walk the context chain to find the context at the given depth. | 1302 // Walk the context chain to find the context at the given depth. |
| 1277 // TODO(rmcilroy): Perform this work in a bytecode handler once we have | 1303 // TODO(rmcilroy): Perform this work in a bytecode handler once we have |
| 1278 // a generic mechanism for performing jumps in interpreter.cc. | 1304 // a generic mechanism for performing jumps in interpreter.cc. |
| 1279 // TODO(mythria): Also update bytecode graph builder with correct depth | 1305 // TODO(mythria): Also update bytecode graph builder with correct depth |
| 1280 // when this changes. | 1306 // when this changes. |
| 1281 builder() | 1307 builder() |
| 1282 ->StoreAccumulatorInRegister(value_temp) | 1308 ->StoreAccumulatorInRegister(value_temp) |
| 1283 .LoadAccumulatorWithRegister(execution_context()->reg()) | 1309 .LoadAccumulatorWithRegister(execution_context()->reg()) |
| 1284 .StoreAccumulatorInRegister(context_reg); | 1310 .StoreAccumulatorInRegister(context_reg); |
| 1285 for (int i = 0; i < depth; ++i) { | 1311 for (int i = 0; i < depth; ++i) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1317 case NAMED_PROPERTY: { | 1343 case NAMED_PROPERTY: { |
| 1318 object = VisitForRegisterValue(property->obj()); | 1344 object = VisitForRegisterValue(property->obj()); |
| 1319 name = property->key()->AsLiteral()->AsPropertyName(); | 1345 name = property->key()->AsLiteral()->AsPropertyName(); |
| 1320 break; | 1346 break; |
| 1321 } | 1347 } |
| 1322 case KEYED_PROPERTY: { | 1348 case KEYED_PROPERTY: { |
| 1323 object = VisitForRegisterValue(property->obj()); | 1349 object = VisitForRegisterValue(property->obj()); |
| 1324 if (expr->is_compound()) { | 1350 if (expr->is_compound()) { |
| 1325 // Use VisitForAccumulator and store to register so that the key is | 1351 // Use VisitForAccumulator and store to register so that the key is |
| 1326 // still in the accumulator for loading the old value below. | 1352 // still in the accumulator for loading the old value below. |
| 1327 key = execution_result()->NewRegister(); | 1353 key = register_allocator()->NewRegister(); |
| 1328 VisitForAccumulatorValue(property->key()); | 1354 VisitForAccumulatorValue(property->key()); |
| 1329 builder()->StoreAccumulatorInRegister(key); | 1355 builder()->StoreAccumulatorInRegister(key); |
| 1330 } else { | 1356 } else { |
| 1331 key = VisitForRegisterValue(property->key()); | 1357 key = VisitForRegisterValue(property->key()); |
| 1332 } | 1358 } |
| 1333 break; | 1359 break; |
| 1334 } | 1360 } |
| 1335 case NAMED_SUPER_PROPERTY: | 1361 case NAMED_SUPER_PROPERTY: |
| 1336 case KEYED_SUPER_PROPERTY: | 1362 case KEYED_SUPER_PROPERTY: |
| 1337 UNIMPLEMENTED(); | 1363 UNIMPLEMENTED(); |
| 1338 } | 1364 } |
| 1339 | 1365 |
| 1340 // Evaluate the value and potentially handle compound assignments by loading | 1366 // Evaluate the value and potentially handle compound assignments by loading |
| 1341 // the left-hand side value and performing a binary operation. | 1367 // the left-hand side value and performing a binary operation. |
| 1342 if (expr->is_compound()) { | 1368 if (expr->is_compound()) { |
| 1343 Register old_value; | 1369 Register old_value; |
| 1344 switch (assign_type) { | 1370 switch (assign_type) { |
| 1345 case VARIABLE: { | 1371 case VARIABLE: { |
| 1346 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 1372 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| 1347 old_value = VisitVariableLoadForRegisterValue( | 1373 old_value = VisitVariableLoadForRegisterValue( |
| 1348 proxy->var(), proxy->VariableFeedbackSlot()); | 1374 proxy->var(), proxy->VariableFeedbackSlot()); |
| 1349 break; | 1375 break; |
| 1350 } | 1376 } |
| 1351 case NAMED_PROPERTY: { | 1377 case NAMED_PROPERTY: { |
| 1352 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 1378 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
| 1353 old_value = execution_result()->NewRegister(); | 1379 old_value = register_allocator()->NewRegister(); |
| 1354 builder() | 1380 builder() |
| 1355 ->LoadNamedProperty(object, name, feedback_index(slot), | 1381 ->LoadNamedProperty(object, name, feedback_index(slot), |
| 1356 language_mode()) | 1382 language_mode()) |
| 1357 .StoreAccumulatorInRegister(old_value); | 1383 .StoreAccumulatorInRegister(old_value); |
| 1358 break; | 1384 break; |
| 1359 } | 1385 } |
| 1360 case KEYED_PROPERTY: { | 1386 case KEYED_PROPERTY: { |
| 1361 // Key is already in accumulator at this point due to evaluating the | 1387 // Key is already in accumulator at this point due to evaluating the |
| 1362 // LHS above. | 1388 // LHS above. |
| 1363 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 1389 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
| 1364 old_value = execution_result()->NewRegister(); | 1390 old_value = register_allocator()->NewRegister(); |
| 1365 builder() | 1391 builder() |
| 1366 ->LoadKeyedProperty(object, feedback_index(slot), language_mode()) | 1392 ->LoadKeyedProperty(object, feedback_index(slot), language_mode()) |
| 1367 .StoreAccumulatorInRegister(old_value); | 1393 .StoreAccumulatorInRegister(old_value); |
| 1368 break; | 1394 break; |
| 1369 } | 1395 } |
| 1370 case NAMED_SUPER_PROPERTY: | 1396 case NAMED_SUPER_PROPERTY: |
| 1371 case KEYED_SUPER_PROPERTY: | 1397 case KEYED_SUPER_PROPERTY: |
| 1372 UNIMPLEMENTED(); | 1398 UNIMPLEMENTED(); |
| 1373 break; | 1399 break; |
| 1374 } | 1400 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1460 // Visit arguments and place in a contiguous block of temporary | 1486 // Visit arguments and place in a contiguous block of temporary |
| 1461 // registers. Return the first temporary register corresponding to | 1487 // registers. Return the first temporary register corresponding to |
| 1462 // the first argument. | 1488 // the first argument. |
| 1463 // | 1489 // |
| 1464 // NB the caller may have already called | 1490 // NB the caller may have already called |
| 1465 // PrepareForConsecutiveAllocations() with args->length() + N. The | 1491 // PrepareForConsecutiveAllocations() with args->length() + N. The |
| 1466 // second call here will be a no-op provided there have been N or | 1492 // second call here will be a no-op provided there have been N or |
| 1467 // less calls to NextConsecutiveRegister(). Otherwise, the arguments | 1493 // less calls to NextConsecutiveRegister(). Otherwise, the arguments |
| 1468 // here will be consecutive, but they will not be consecutive with | 1494 // here will be consecutive, but they will not be consecutive with |
| 1469 // earlier consecutive allocations made by the caller. | 1495 // earlier consecutive allocations made by the caller. |
| 1470 execution_result()->PrepareForConsecutiveAllocations(args->length()); | 1496 register_allocator()->PrepareForConsecutiveAllocations(args->length()); |
| 1471 | 1497 |
| 1472 // Visit for first argument that goes into returned register | 1498 // Visit for first argument that goes into returned register |
| 1473 Register first_arg = execution_result()->NextConsecutiveRegister(); | 1499 Register first_arg = register_allocator()->NextConsecutiveRegister(); |
| 1474 VisitForAccumulatorValue(args->at(0)); | 1500 VisitForAccumulatorValue(args->at(0)); |
| 1475 builder()->StoreAccumulatorInRegister(first_arg); | 1501 builder()->StoreAccumulatorInRegister(first_arg); |
| 1476 | 1502 |
| 1477 // Visit remaining arguments | 1503 // Visit remaining arguments |
| 1478 for (int i = 1; i < static_cast<int>(args->length()); i++) { | 1504 for (int i = 1; i < static_cast<int>(args->length()); i++) { |
| 1479 Register ith_arg = execution_result()->NextConsecutiveRegister(); | 1505 Register ith_arg = register_allocator()->NextConsecutiveRegister(); |
| 1480 VisitForAccumulatorValue(args->at(i)); | 1506 VisitForAccumulatorValue(args->at(i)); |
| 1481 builder()->StoreAccumulatorInRegister(ith_arg); | 1507 builder()->StoreAccumulatorInRegister(ith_arg); |
| 1482 DCHECK(ith_arg.index() - i == first_arg.index()); | 1508 DCHECK(ith_arg.index() - i == first_arg.index()); |
| 1483 } | 1509 } |
| 1484 return first_arg; | 1510 return first_arg; |
| 1485 } | 1511 } |
| 1486 | 1512 |
| 1487 | 1513 |
| 1488 void BytecodeGenerator::VisitCall(Call* expr) { | 1514 void BytecodeGenerator::VisitCall(Call* expr) { |
| 1489 Expression* callee_expr = expr->expression(); | 1515 Expression* callee_expr = expr->expression(); |
| 1490 Call::CallType call_type = expr->GetCallType(isolate()); | 1516 Call::CallType call_type = expr->GetCallType(isolate()); |
| 1491 | 1517 |
| 1492 // Prepare the callee and the receiver to the function call. This depends on | 1518 // Prepare the callee and the receiver to the function call. This depends on |
| 1493 // the semantics of the underlying call type. | 1519 // the semantics of the underlying call type. |
| 1494 | 1520 |
| 1495 // The receiver and arguments need to be allocated consecutively for | 1521 // The receiver and arguments need to be allocated consecutively for |
| 1496 // Call(). We allocate the callee and receiver consecutively for calls to | 1522 // Call(). We allocate the callee and receiver consecutively for calls to |
| 1497 // kLoadLookupSlot. Future optimizations could avoid this there are no | 1523 // kLoadLookupSlot. Future optimizations could avoid this there are no |
| 1498 // arguments or the receiver and arguments are already consecutive. | 1524 // arguments or the receiver and arguments are already consecutive. |
| 1499 ZoneList<Expression*>* args = expr->arguments(); | 1525 ZoneList<Expression*>* args = expr->arguments(); |
| 1500 execution_result()->PrepareForConsecutiveAllocations(args->length() + 2); | 1526 register_allocator()->PrepareForConsecutiveAllocations(args->length() + 2); |
| 1501 Register callee = execution_result()->NextConsecutiveRegister(); | 1527 Register callee = register_allocator()->NextConsecutiveRegister(); |
| 1502 Register receiver = execution_result()->NextConsecutiveRegister(); | 1528 Register receiver = register_allocator()->NextConsecutiveRegister(); |
| 1503 | 1529 |
| 1504 switch (call_type) { | 1530 switch (call_type) { |
| 1505 case Call::NAMED_PROPERTY_CALL: | 1531 case Call::NAMED_PROPERTY_CALL: |
| 1506 case Call::KEYED_PROPERTY_CALL: { | 1532 case Call::KEYED_PROPERTY_CALL: { |
| 1507 Property* property = callee_expr->AsProperty(); | 1533 Property* property = callee_expr->AsProperty(); |
| 1508 VisitForAccumulatorValue(property->obj()); | 1534 VisitForAccumulatorValue(property->obj()); |
| 1509 builder()->StoreAccumulatorInRegister(receiver); | 1535 builder()->StoreAccumulatorInRegister(receiver); |
| 1510 VisitPropertyLoadForAccumulator(receiver, property); | 1536 VisitPropertyLoadForAccumulator(receiver, property); |
| 1511 builder()->StoreAccumulatorInRegister(callee); | 1537 builder()->StoreAccumulatorInRegister(callee); |
| 1512 break; | 1538 break; |
| 1513 } | 1539 } |
| 1514 case Call::GLOBAL_CALL: { | 1540 case Call::GLOBAL_CALL: { |
| 1515 // Receiver is undefined for global calls. | 1541 // Receiver is undefined for global calls. |
| 1516 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 1542 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
| 1517 // Load callee as a global variable. | 1543 // Load callee as a global variable. |
| 1518 VariableProxy* proxy = callee_expr->AsVariableProxy(); | 1544 VariableProxy* proxy = callee_expr->AsVariableProxy(); |
| 1519 VisitVariableLoadForAccumulatorValue(proxy->var(), | 1545 VisitVariableLoadForAccumulatorValue(proxy->var(), |
| 1520 proxy->VariableFeedbackSlot()); | 1546 proxy->VariableFeedbackSlot()); |
| 1521 builder()->StoreAccumulatorInRegister(callee); | 1547 builder()->StoreAccumulatorInRegister(callee); |
| 1522 break; | 1548 break; |
| 1523 } | 1549 } |
| 1524 case Call::LOOKUP_SLOT_CALL: | 1550 case Call::LOOKUP_SLOT_CALL: |
| 1525 case Call::POSSIBLY_EVAL_CALL: { | 1551 case Call::POSSIBLY_EVAL_CALL: { |
| 1526 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { | 1552 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) { |
| 1527 TemporaryRegisterScope temporary_register_scope(builder()); | 1553 RegisterAllocationScope inner_register_scope(this); |
| 1528 temporary_register_scope.PrepareForConsecutiveAllocations(2); | 1554 register_allocator()->PrepareForConsecutiveAllocations(2); |
| 1529 Register context = temporary_register_scope.NextConsecutiveRegister(); | 1555 Register context = register_allocator()->NextConsecutiveRegister(); |
| 1530 Register name = temporary_register_scope.NextConsecutiveRegister(); | 1556 Register name = register_allocator()->NextConsecutiveRegister(); |
| 1531 | 1557 |
| 1532 // Call LoadLookupSlot to get the callee and receiver. | 1558 // Call LoadLookupSlot to get the callee and receiver. |
| 1533 DCHECK(Register::AreContiguous(callee, receiver)); | 1559 DCHECK(Register::AreContiguous(callee, receiver)); |
| 1534 Variable* variable = callee_expr->AsVariableProxy()->var(); | 1560 Variable* variable = callee_expr->AsVariableProxy()->var(); |
| 1535 builder() | 1561 builder() |
| 1536 ->MoveRegister(Register::function_context(), context) | 1562 ->MoveRegister(Register::function_context(), context) |
| 1537 .LoadLiteral(variable->name()) | 1563 .LoadLiteral(variable->name()) |
| 1538 .StoreAccumulatorInRegister(name) | 1564 .StoreAccumulatorInRegister(name) |
| 1539 .CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, callee); | 1565 .CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, callee); |
| 1540 break; | 1566 break; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1555 } | 1581 } |
| 1556 | 1582 |
| 1557 // Evaluate all arguments to the function call and store in sequential | 1583 // Evaluate all arguments to the function call and store in sequential |
| 1558 // registers. | 1584 // registers. |
| 1559 Register arg = VisitArguments(args); | 1585 Register arg = VisitArguments(args); |
| 1560 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1); | 1586 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1); |
| 1561 | 1587 |
| 1562 // Resolve callee for a potential direct eval call. This block will mutate the | 1588 // Resolve callee for a potential direct eval call. This block will mutate the |
| 1563 // callee value. | 1589 // callee value. |
| 1564 if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) { | 1590 if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) { |
| 1565 TemporaryRegisterScope temporary_register_scope(builder()); | 1591 RegisterAllocationScope inner_register_scope(this); |
| 1566 temporary_register_scope.PrepareForConsecutiveAllocations(5); | 1592 register_allocator()->PrepareForConsecutiveAllocations(5); |
| 1567 Register callee_for_eval = | 1593 Register callee_for_eval = register_allocator()->NextConsecutiveRegister(); |
| 1568 temporary_register_scope.NextConsecutiveRegister(); | 1594 Register source = register_allocator()->NextConsecutiveRegister(); |
| 1569 Register source = temporary_register_scope.NextConsecutiveRegister(); | 1595 Register function = register_allocator()->NextConsecutiveRegister(); |
| 1570 Register function = temporary_register_scope.NextConsecutiveRegister(); | 1596 Register language = register_allocator()->NextConsecutiveRegister(); |
| 1571 Register language = temporary_register_scope.NextConsecutiveRegister(); | 1597 Register position = register_allocator()->NextConsecutiveRegister(); |
| 1572 Register position = temporary_register_scope.NextConsecutiveRegister(); | |
| 1573 | 1598 |
| 1574 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source | 1599 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source |
| 1575 // strings and function closure, and loading language and | 1600 // strings and function closure, and loading language and |
| 1576 // position. | 1601 // position. |
| 1577 builder() | 1602 builder() |
| 1578 ->MoveRegister(callee, callee_for_eval) | 1603 ->MoveRegister(callee, callee_for_eval) |
| 1579 .MoveRegister(arg, source) | 1604 .MoveRegister(arg, source) |
| 1580 .MoveRegister(Register::function_closure(), function) | 1605 .MoveRegister(Register::function_closure(), function) |
| 1581 .LoadLiteral(Smi::FromInt(language_mode())) | 1606 .LoadLiteral(Smi::FromInt(language_mode())) |
| 1582 .StoreAccumulatorInRegister(language) | 1607 .StoreAccumulatorInRegister(language) |
| 1583 .LoadLiteral( | 1608 .LoadLiteral( |
| 1584 Smi::FromInt(execution_context()->scope()->start_position())) | 1609 Smi::FromInt(execution_context()->scope()->start_position())) |
| 1585 .StoreAccumulatorInRegister(position); | 1610 .StoreAccumulatorInRegister(position); |
| 1586 | 1611 |
| 1587 // Call ResolvePossiblyDirectEval and modify the callee. | 1612 // Call ResolvePossiblyDirectEval and modify the callee. |
| 1588 builder() | 1613 builder() |
| 1589 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 5) | 1614 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 5) |
| 1590 .StoreAccumulatorInRegister(callee); | 1615 .StoreAccumulatorInRegister(callee); |
| 1591 } | 1616 } |
| 1592 | 1617 |
| 1593 // TODO(rmcilroy): Use CallIC to allow call type feedback. | 1618 // TODO(rmcilroy): Use CallIC to allow call type feedback. |
| 1594 builder()->Call(callee, receiver, args->length(), | 1619 builder()->Call(callee, receiver, args->length(), |
| 1595 feedback_index(expr->CallFeedbackICSlot())); | 1620 feedback_index(expr->CallFeedbackICSlot())); |
| 1596 execution_result()->SetResultInAccumulator(); | 1621 execution_result()->SetResultInAccumulator(); |
| 1597 } | 1622 } |
| 1598 | 1623 |
| 1599 | 1624 |
| 1600 void BytecodeGenerator::VisitCallNew(CallNew* expr) { | 1625 void BytecodeGenerator::VisitCallNew(CallNew* expr) { |
| 1601 Register constructor = execution_result()->NewRegister(); | 1626 Register constructor = register_allocator()->NewRegister(); |
| 1602 VisitForAccumulatorValue(expr->expression()); | 1627 VisitForAccumulatorValue(expr->expression()); |
| 1603 builder()->StoreAccumulatorInRegister(constructor); | 1628 builder()->StoreAccumulatorInRegister(constructor); |
| 1604 | 1629 |
| 1605 ZoneList<Expression*>* args = expr->arguments(); | 1630 ZoneList<Expression*>* args = expr->arguments(); |
| 1606 Register first_arg = VisitArguments(args); | 1631 Register first_arg = VisitArguments(args); |
| 1607 builder()->New(constructor, first_arg, args->length()); | 1632 builder()->New(constructor, first_arg, args->length()); |
| 1608 execution_result()->SetResultInAccumulator(); | 1633 execution_result()->SetResultInAccumulator(); |
| 1609 } | 1634 } |
| 1610 | 1635 |
| 1611 | 1636 |
| 1612 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1637 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 1613 ZoneList<Expression*>* args = expr->arguments(); | 1638 ZoneList<Expression*>* args = expr->arguments(); |
| 1614 Register receiver; | 1639 Register receiver; |
| 1615 if (expr->is_jsruntime()) { | 1640 if (expr->is_jsruntime()) { |
| 1616 // Allocate a register for the receiver and load it with undefined. | 1641 // Allocate a register for the receiver and load it with undefined. |
| 1617 execution_result()->PrepareForConsecutiveAllocations(args->length() + 1); | 1642 register_allocator()->PrepareForConsecutiveAllocations(args->length() + 1); |
| 1618 receiver = execution_result()->NextConsecutiveRegister(); | 1643 receiver = register_allocator()->NextConsecutiveRegister(); |
| 1619 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 1644 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
| 1620 } | 1645 } |
| 1621 // Evaluate all arguments to the runtime call. | 1646 // Evaluate all arguments to the runtime call. |
| 1622 Register first_arg = VisitArguments(args); | 1647 Register first_arg = VisitArguments(args); |
| 1623 | 1648 |
| 1624 if (expr->is_jsruntime()) { | 1649 if (expr->is_jsruntime()) { |
| 1625 DCHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1); | 1650 DCHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1); |
| 1626 builder()->CallJSRuntime(expr->context_index(), receiver, args->length()); | 1651 builder()->CallJSRuntime(expr->context_index(), receiver, args->length()); |
| 1627 } else { | 1652 } else { |
| 1628 Runtime::FunctionId function_id = expr->function()->function_id; | 1653 Runtime::FunctionId function_id = expr->function()->function_id; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1698 } else if (expr->expression()->IsVariableProxy()) { | 1723 } else if (expr->expression()->IsVariableProxy()) { |
| 1699 // Delete of an unqualified identifier is allowed in sloppy mode but is | 1724 // Delete of an unqualified identifier is allowed in sloppy mode but is |
| 1700 // not allowed in strict mode. Deleting 'this' is allowed in both modes. | 1725 // not allowed in strict mode. Deleting 'this' is allowed in both modes. |
| 1701 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 1726 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 1702 Variable* variable = proxy->var(); | 1727 Variable* variable = proxy->var(); |
| 1703 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate())); | 1728 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate())); |
| 1704 switch (variable->location()) { | 1729 switch (variable->location()) { |
| 1705 case VariableLocation::GLOBAL: | 1730 case VariableLocation::GLOBAL: |
| 1706 case VariableLocation::UNALLOCATED: { | 1731 case VariableLocation::UNALLOCATED: { |
| 1707 // Global var, let, const or variables not explicitly declared. | 1732 // Global var, let, const or variables not explicitly declared. |
| 1708 Register native_context = execution_result()->NewRegister(); | 1733 Register native_context = register_allocator()->NewRegister(); |
| 1709 Register global_object = execution_result()->NewRegister(); | 1734 Register global_object = register_allocator()->NewRegister(); |
| 1710 builder() | 1735 builder() |
| 1711 ->LoadContextSlot(execution_context()->reg(), | 1736 ->LoadContextSlot(execution_context()->reg(), |
| 1712 Context::NATIVE_CONTEXT_INDEX) | 1737 Context::NATIVE_CONTEXT_INDEX) |
| 1713 .StoreAccumulatorInRegister(native_context) | 1738 .StoreAccumulatorInRegister(native_context) |
| 1714 .LoadContextSlot(native_context, Context::EXTENSION_INDEX) | 1739 .LoadContextSlot(native_context, Context::EXTENSION_INDEX) |
| 1715 .StoreAccumulatorInRegister(global_object) | 1740 .StoreAccumulatorInRegister(global_object) |
| 1716 .LoadLiteral(variable->name()) | 1741 .LoadLiteral(variable->name()) |
| 1717 .Delete(global_object, language_mode()); | 1742 .Delete(global_object, language_mode()); |
| 1718 break; | 1743 break; |
| 1719 } | 1744 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1771 name = property->key()->AsLiteral()->AsPropertyName(); | 1796 name = property->key()->AsLiteral()->AsPropertyName(); |
| 1772 builder()->LoadNamedProperty(obj, name, feedback_index(slot), | 1797 builder()->LoadNamedProperty(obj, name, feedback_index(slot), |
| 1773 language_mode()); | 1798 language_mode()); |
| 1774 break; | 1799 break; |
| 1775 } | 1800 } |
| 1776 case KEYED_PROPERTY: { | 1801 case KEYED_PROPERTY: { |
| 1777 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); | 1802 FeedbackVectorSlot slot = property->PropertyFeedbackSlot(); |
| 1778 obj = VisitForRegisterValue(property->obj()); | 1803 obj = VisitForRegisterValue(property->obj()); |
| 1779 // Use visit for accumulator here since we need the key in the accumulator | 1804 // Use visit for accumulator here since we need the key in the accumulator |
| 1780 // for the LoadKeyedProperty. | 1805 // for the LoadKeyedProperty. |
| 1781 key = execution_result()->NewRegister(); | 1806 key = register_allocator()->NewRegister(); |
| 1782 VisitForAccumulatorValue(property->key()); | 1807 VisitForAccumulatorValue(property->key()); |
| 1783 builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty( | 1808 builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty( |
| 1784 obj, feedback_index(slot), language_mode()); | 1809 obj, feedback_index(slot), language_mode()); |
| 1785 break; | 1810 break; |
| 1786 } | 1811 } |
| 1787 case NAMED_SUPER_PROPERTY: | 1812 case NAMED_SUPER_PROPERTY: |
| 1788 case KEYED_SUPER_PROPERTY: | 1813 case KEYED_SUPER_PROPERTY: |
| 1789 UNIMPLEMENTED(); | 1814 UNIMPLEMENTED(); |
| 1790 } | 1815 } |
| 1791 | 1816 |
| 1792 // Convert old value into a number. | 1817 // Convert old value into a number. |
| 1793 if (!is_strong(language_mode())) { | 1818 if (!is_strong(language_mode())) { |
| 1794 builder()->CastAccumulatorToNumber(); | 1819 builder()->CastAccumulatorToNumber(); |
| 1795 } | 1820 } |
| 1796 | 1821 |
| 1797 // Save result for postfix expressions. | 1822 // Save result for postfix expressions. |
| 1798 if (is_postfix) { | 1823 if (is_postfix) { |
| 1799 old_value = execution_result()->outer()->NewRegister(); | 1824 old_value = register_allocator()->outer()->NewRegister(); |
| 1800 builder()->StoreAccumulatorInRegister(old_value); | 1825 builder()->StoreAccumulatorInRegister(old_value); |
| 1801 } | 1826 } |
| 1802 | 1827 |
| 1803 // Perform +1/-1 operation. | 1828 // Perform +1/-1 operation. |
| 1804 builder()->CountOperation(expr->binary_op(), language_mode_strength()); | 1829 builder()->CountOperation(expr->binary_op(), language_mode_strength()); |
| 1805 | 1830 |
| 1806 // Store the value. | 1831 // Store the value. |
| 1807 FeedbackVectorSlot feedback_slot = expr->CountSlot(); | 1832 FeedbackVectorSlot feedback_slot = expr->CountSlot(); |
| 1808 switch (assign_type) { | 1833 switch (assign_type) { |
| 1809 case VARIABLE: { | 1834 case VARIABLE: { |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1942 Visit(expr->expression()); | 1967 Visit(expr->expression()); |
| 1943 } | 1968 } |
| 1944 | 1969 |
| 1945 | 1970 |
| 1946 void BytecodeGenerator::VisitNewLocalFunctionContext() { | 1971 void BytecodeGenerator::VisitNewLocalFunctionContext() { |
| 1947 AccumulatorResultScope accumulator_execution_result(this); | 1972 AccumulatorResultScope accumulator_execution_result(this); |
| 1948 Scope* scope = this->scope(); | 1973 Scope* scope = this->scope(); |
| 1949 | 1974 |
| 1950 // Allocate a new local context. | 1975 // Allocate a new local context. |
| 1951 if (scope->is_script_scope()) { | 1976 if (scope->is_script_scope()) { |
| 1952 TemporaryRegisterScope temporary_register_scope(builder()); | 1977 RegisterAllocationScope register_scope(this); |
| 1953 Register closure = temporary_register_scope.NewRegister(); | 1978 Register closure = register_allocator()->NewRegister(); |
| 1954 Register scope_info = temporary_register_scope.NewRegister(); | 1979 Register scope_info = register_allocator()->NewRegister(); |
| 1955 DCHECK(Register::AreContiguous(closure, scope_info)); | 1980 DCHECK(Register::AreContiguous(closure, scope_info)); |
| 1956 builder() | 1981 builder() |
| 1957 ->LoadAccumulatorWithRegister(Register::function_closure()) | 1982 ->LoadAccumulatorWithRegister(Register::function_closure()) |
| 1958 .StoreAccumulatorInRegister(closure) | 1983 .StoreAccumulatorInRegister(closure) |
| 1959 .LoadLiteral(scope->GetScopeInfo(isolate())) | 1984 .LoadLiteral(scope->GetScopeInfo(isolate())) |
| 1960 .StoreAccumulatorInRegister(scope_info) | 1985 .StoreAccumulatorInRegister(scope_info) |
| 1961 .CallRuntime(Runtime::kNewScriptContext, closure, 2); | 1986 .CallRuntime(Runtime::kNewScriptContext, closure, 2); |
| 1962 } else { | 1987 } else { |
| 1963 builder()->CallRuntime(Runtime::kNewFunctionContext, | 1988 builder()->CallRuntime(Runtime::kNewFunctionContext, |
| 1964 Register::function_closure(), 1); | 1989 Register::function_closure(), 1); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1994 .StoreContextSlot(execution_context()->reg(), variable->index()); | 2019 .StoreContextSlot(execution_context()->reg(), variable->index()); |
| 1995 } | 2020 } |
| 1996 } | 2021 } |
| 1997 | 2022 |
| 1998 | 2023 |
| 1999 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) { | 2024 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) { |
| 2000 AccumulatorResultScope accumulator_execution_result(this); | 2025 AccumulatorResultScope accumulator_execution_result(this); |
| 2001 DCHECK(scope->is_block_scope()); | 2026 DCHECK(scope->is_block_scope()); |
| 2002 | 2027 |
| 2003 // Allocate a new local block context. | 2028 // Allocate a new local block context. |
| 2004 TemporaryRegisterScope temporary_register_scope(builder()); | 2029 register_allocator()->PrepareForConsecutiveAllocations(2); |
| 2005 temporary_register_scope.PrepareForConsecutiveAllocations(2); | 2030 Register scope_info = register_allocator()->NextConsecutiveRegister(); |
| 2006 Register scope_info = temporary_register_scope.NextConsecutiveRegister(); | 2031 Register closure = register_allocator()->NextConsecutiveRegister(); |
| 2007 Register closure = temporary_register_scope.NextConsecutiveRegister(); | |
| 2008 | 2032 |
| 2009 builder() | 2033 builder() |
| 2010 ->LoadLiteral(scope->GetScopeInfo(isolate())) | 2034 ->LoadLiteral(scope->GetScopeInfo(isolate())) |
| 2011 .StoreAccumulatorInRegister(scope_info); | 2035 .StoreAccumulatorInRegister(scope_info); |
| 2012 VisitFunctionClosureForContext(); | 2036 VisitFunctionClosureForContext(); |
| 2013 builder() | 2037 builder() |
| 2014 ->StoreAccumulatorInRegister(closure) | 2038 ->StoreAccumulatorInRegister(closure) |
| 2015 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2); | 2039 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2); |
| 2016 execution_result()->SetResultInAccumulator(); | 2040 execution_result()->SetResultInAccumulator(); |
| 2017 } | 2041 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2077 } | 2101 } |
| 2078 | 2102 |
| 2079 | 2103 |
| 2080 void BytecodeGenerator::VisitFunctionClosureForContext() { | 2104 void BytecodeGenerator::VisitFunctionClosureForContext() { |
| 2081 AccumulatorResultScope accumulator_execution_result(this); | 2105 AccumulatorResultScope accumulator_execution_result(this); |
| 2082 Scope* closure_scope = execution_context()->scope()->ClosureScope(); | 2106 Scope* closure_scope = execution_context()->scope()->ClosureScope(); |
| 2083 if (closure_scope->is_script_scope() || | 2107 if (closure_scope->is_script_scope() || |
| 2084 closure_scope->is_module_scope()) { | 2108 closure_scope->is_module_scope()) { |
| 2085 // Contexts nested in the native context have a canonical empty function as | 2109 // Contexts nested in the native context have a canonical empty function as |
| 2086 // their closure, not the anonymous closure containing the global code. | 2110 // their closure, not the anonymous closure containing the global code. |
| 2087 Register native_context = execution_result()->NewRegister(); | 2111 Register native_context = register_allocator()->NewRegister(); |
| 2088 builder() | 2112 builder() |
| 2089 ->LoadContextSlot(execution_context()->reg(), | 2113 ->LoadContextSlot(execution_context()->reg(), |
| 2090 Context::NATIVE_CONTEXT_INDEX) | 2114 Context::NATIVE_CONTEXT_INDEX) |
| 2091 .StoreAccumulatorInRegister(native_context) | 2115 .StoreAccumulatorInRegister(native_context) |
| 2092 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); | 2116 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); |
| 2093 } else { | 2117 } else { |
| 2094 DCHECK(closure_scope->is_function_scope()); | 2118 DCHECK(closure_scope->is_function_scope()); |
| 2095 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 2119 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 2096 } | 2120 } |
| 2097 execution_result()->SetResultInAccumulator(); | 2121 execution_result()->SetResultInAccumulator(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2149 } | 2173 } |
| 2150 | 2174 |
| 2151 | 2175 |
| 2152 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2176 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 2153 return info()->feedback_vector()->GetIndex(slot); | 2177 return info()->feedback_vector()->GetIndex(slot); |
| 2154 } | 2178 } |
| 2155 | 2179 |
| 2156 } // namespace interpreter | 2180 } // namespace interpreter |
| 2157 } // namespace internal | 2181 } // namespace internal |
| 2158 } // namespace v8 | 2182 } // namespace v8 |
| OLD | NEW |