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 |