Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(304)

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 1392933002: [Interpreter] Reduce temporary register usage in generated bytecode. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Missed comments. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <stack>
8
9 #include "src/compiler.h" 7 #include "src/compiler.h"
10 #include "src/interpreter/control-flow-builders.h" 8 #include "src/interpreter/control-flow-builders.h"
11 #include "src/objects.h" 9 #include "src/objects.h"
12 #include "src/parser.h" 10 #include "src/parser.h"
13 #include "src/scopes.h" 11 #include "src/scopes.h"
14 #include "src/token.h" 12 #include "src/token.h"
15 13
16 namespace v8 { 14 namespace v8 {
17 namespace internal { 15 namespace internal {
18 namespace interpreter { 16 namespace interpreter {
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 Statement* statement) { 137 Statement* statement) {
140 ControlScope* current = this; 138 ControlScope* current = this;
141 do { 139 do {
142 if (current->Execute(command, statement)) return; 140 if (current->Execute(command, statement)) return;
143 current = current->outer(); 141 current = current->outer();
144 } while (current != nullptr); 142 } while (current != nullptr);
145 UNREACHABLE(); 143 UNREACHABLE();
146 } 144 }
147 145
148 146
147 // Scoped base class for determining where the result of an expression
148 // is stored.
149 class BytecodeGenerator::ExpressionResultScope {
150 public:
151 explicit ExpressionResultScope(BytecodeGenerator* generator)
152 : generator_(generator),
153 outer_(generator->result_scope()),
154 allocator_(builder()),
155 result_identified_(false) {
156 generator_->set_result_scope(this);
157 }
158
159 virtual ~ExpressionResultScope() {
160 generator_->set_result_scope(outer_);
161 DCHECK_EQ(result_identified(), true);
162 }
163
164 virtual void SetResultInAccumulator() = 0;
165 virtual void SetResultInRegister(Register reg) = 0;
166
167 BytecodeGenerator* generator() const { return generator_; }
168 BytecodeArrayBuilder* builder() const { return generator()->builder(); }
169 ExpressionResultScope* outer() const { return outer_; }
170
171 Register NewRegister() { return allocator_.NewRegister(); }
172
173 void PrepareForConsecutiveAllocations(size_t count) {
174 allocator_.PrepareForConsecutiveAllocations(count);
175 }
176
177 Register NextConsecutiveRegister() {
178 return allocator_.NextConsecutiveRegister();
179 }
180
181 protected:
182 void set_result_identified() {
183 DCHECK(!result_identified());
184 result_identified_ = true;
185 }
186
187 bool result_identified() const { return result_identified_; }
188
189 private:
190 BytecodeGenerator* generator_;
191 ExpressionResultScope* outer_;
192 TemporaryRegisterScope allocator_;
193 bool result_identified_;
194 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
195 };
196
197
198 // Scoped class used when the result of the current expression is not
199 // expected to produce a result.
200 class BytecodeGenerator::EffectResultScope final
201 : public ExpressionResultScope {
202 public:
203 explicit EffectResultScope(BytecodeGenerator* generator)
204 : ExpressionResultScope(generator) {
205 set_result_identified();
206 }
207
208 virtual void SetResultInAccumulator() {}
209 virtual void SetResultInRegister(Register reg) {}
210 };
211
212
213 // Scoped class used when the result of the current expression to be
214 // evaluated should go into the interpreter's accumulator register.
215 class BytecodeGenerator::AccumulatorResultScope final
216 : public ExpressionResultScope {
217 public:
218 explicit AccumulatorResultScope(BytecodeGenerator* generator)
219 : ExpressionResultScope(generator) {}
220
221 virtual void SetResultInAccumulator() { set_result_identified(); }
222
223 virtual void SetResultInRegister(Register reg) {
224 builder()->LoadAccumulatorWithRegister(reg);
225 set_result_identified();
226 }
227 };
228
229
230 // Scoped class used when the result of the current expression to be
231 // evaluated should go into an interpreter register.
232 class BytecodeGenerator::RegisterResultScope final
233 : public ExpressionResultScope {
234 public:
235 explicit RegisterResultScope(BytecodeGenerator* generator)
236 : ExpressionResultScope(generator) {}
237 ~RegisterResultScope() {}
238
239 virtual void SetResultInAccumulator() {
240 result_register_ = outer()->NewRegister();
241 builder()->StoreAccumulatorInRegister(result_register_);
242 set_result_identified();
243 }
244
245 virtual void SetResultInRegister(Register reg) {
246 DCHECK(builder()->RegisterIsParameterOrLocal(reg) ||
247 builder()->RegisterIsTemporary(reg));
248 result_register_ = reg;
249 set_result_identified();
250 }
251
252 Register ResultRegister() const { return result_register_; }
253
254 private:
255 Register result_register_;
256 };
257
258
149 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) 259 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
150 : isolate_(isolate), 260 : isolate_(isolate),
151 zone_(zone), 261 zone_(zone),
152 builder_(isolate, zone), 262 builder_(isolate, zone),
153 info_(nullptr), 263 info_(nullptr),
154 scope_(nullptr), 264 scope_(nullptr),
155 globals_(0, zone), 265 globals_(0, zone),
156 execution_control_(nullptr), 266 execution_control_(nullptr),
157 execution_context_(nullptr) { 267 execution_context_(nullptr),
268 result_scope_(nullptr),
269 binary_expression_depth_(0),
270 binary_expression_hazard_set_(zone) {
158 InitializeAstVisitor(isolate); 271 InitializeAstVisitor(isolate);
159 } 272 }
160 273
161 274
162 BytecodeGenerator::~BytecodeGenerator() {} 275 BytecodeGenerator::~BytecodeGenerator() {}
163 276
164 277
165 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { 278 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
166 set_info(info); 279 set_info(info);
167 set_scope(info->scope()); 280 set_scope(info->scope());
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); 430 builder()->LoadLiteral(Smi::FromInt(encoded_flags));
318 builder()->StoreAccumulatorInRegister(flags); 431 builder()->StoreAccumulatorInRegister(flags);
319 DCHECK(flags.index() == pairs.index() + 1); 432 DCHECK(flags.index() == pairs.index() + 1);
320 433
321 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); 434 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2);
322 globals()->clear(); 435 globals()->clear();
323 } 436 }
324 437
325 438
326 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 439 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
327 Visit(stmt->expression()); 440 VisitForEffect(stmt->expression());
328 } 441 }
329 442
330 443
331 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 444 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
332 // TODO(oth): For control-flow it could be useful to signal empty paths here.
333 } 445 }
334 446
335 447
336 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { 448 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
337 // TODO(oth): Spot easy cases where there code would not need to 449 // TODO(oth): Spot easy cases where there code would not need to
338 // emit the then block or the else block, e.g. condition is 450 // emit the then block or the else block, e.g. condition is
339 // obviously true/1/false/0. 451 // obviously true/1/false/0.
340 452
341 BytecodeLabel else_label, end_label; 453 BytecodeLabel else_label, end_label;
342 454
343 Visit(stmt->condition()); 455 VisitForAccumulatorValue(stmt->condition());
344 builder()->CastAccumulatorToBoolean(); 456 builder()->CastAccumulatorToBoolean();
345 builder()->JumpIfFalse(&else_label); 457 builder()->JumpIfFalse(&else_label);
346 Visit(stmt->then_statement()); 458 Visit(stmt->then_statement());
347 if (stmt->HasElseStatement()) { 459 if (stmt->HasElseStatement()) {
348 builder()->Jump(&end_label); 460 builder()->Jump(&end_label);
349 builder()->Bind(&else_label); 461 builder()->Bind(&else_label);
350 Visit(stmt->else_statement()); 462 Visit(stmt->else_statement());
351 } else { 463 } else {
352 builder()->Bind(&else_label); 464 builder()->Bind(&else_label);
353 } 465 }
(...skipping 11 matching lines...) Expand all
365 execution_control()->Continue(stmt->target()); 477 execution_control()->Continue(stmt->target());
366 } 478 }
367 479
368 480
369 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 481 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
370 execution_control()->Break(stmt->target()); 482 execution_control()->Break(stmt->target());
371 } 483 }
372 484
373 485
374 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 486 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
375 Visit(stmt->expression()); 487 VisitForAccumulatorValue(stmt->expression());
376 builder()->Return(); 488 builder()->Return();
377 } 489 }
378 490
379 491
380 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { 492 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
381 UNIMPLEMENTED(); 493 UNIMPLEMENTED();
382 } 494 }
383 495
384 496
385 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 497 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
386 UNIMPLEMENTED(); 498 UNIMPLEMENTED();
387 } 499 }
388 500
389 501
390 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } 502 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); }
391 503
392 504
393 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 505 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
394 LoopBuilder loop_builder(builder()); 506 LoopBuilder loop_builder(builder());
395 ControlScopeForIteration execution_control(this, stmt, &loop_builder); 507 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
396 508
397 BytecodeLabel body_label, condition_label, done_label; 509 BytecodeLabel body_label, condition_label, done_label;
398 builder()->Bind(&body_label); 510 builder()->Bind(&body_label);
399 Visit(stmt->body()); 511 Visit(stmt->body());
400 builder()->Bind(&condition_label); 512 builder()->Bind(&condition_label);
401 Visit(stmt->cond()); 513 VisitForAccumulatorValue(stmt->cond());
402 builder()->JumpIfTrue(&body_label); 514 builder()->JumpIfTrue(&body_label);
403 builder()->Bind(&done_label); 515 builder()->Bind(&done_label);
404 516
405 loop_builder.SetBreakTarget(done_label); 517 loop_builder.SetBreakTarget(done_label);
406 loop_builder.SetContinueTarget(condition_label); 518 loop_builder.SetContinueTarget(condition_label);
407 } 519 }
408 520
409 521
410 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 522 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
411 LoopBuilder loop_builder(builder()); 523 LoopBuilder loop_builder(builder());
412 ControlScopeForIteration execution_control(this, stmt, &loop_builder); 524 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
413 525
414 BytecodeLabel body_label, condition_label, done_label; 526 BytecodeLabel body_label, condition_label, done_label;
415 builder()->Jump(&condition_label); 527 builder()->Jump(&condition_label);
416 builder()->Bind(&body_label); 528 builder()->Bind(&body_label);
417 Visit(stmt->body()); 529 Visit(stmt->body());
418 builder()->Bind(&condition_label); 530 builder()->Bind(&condition_label);
419 Visit(stmt->cond()); 531 VisitForAccumulatorValue(stmt->cond());
420 builder()->JumpIfTrue(&body_label); 532 builder()->JumpIfTrue(&body_label);
421 builder()->Bind(&done_label); 533 builder()->Bind(&done_label);
422 534
423 loop_builder.SetBreakTarget(done_label); 535 loop_builder.SetBreakTarget(done_label);
424 loop_builder.SetContinueTarget(condition_label); 536 loop_builder.SetContinueTarget(condition_label);
425 } 537 }
426 538
427 539
428 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { 540 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
429 LoopBuilder loop_builder(builder()); 541 LoopBuilder loop_builder(builder());
430 ControlScopeForIteration execution_control(this, stmt, &loop_builder); 542 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
431 543
432 if (stmt->init() != nullptr) { 544 if (stmt->init() != nullptr) {
433 Visit(stmt->init()); 545 Visit(stmt->init());
434 } 546 }
435 547
436 BytecodeLabel body_label, condition_label, next_label, done_label; 548 BytecodeLabel body_label, condition_label, next_label, done_label;
437 if (stmt->cond() != nullptr) { 549 if (stmt->cond() != nullptr) {
438 builder()->Jump(&condition_label); 550 builder()->Jump(&condition_label);
439 } 551 }
440 builder()->Bind(&body_label); 552 builder()->Bind(&body_label);
441 Visit(stmt->body()); 553 Visit(stmt->body());
442 builder()->Bind(&next_label); 554 builder()->Bind(&next_label);
443 if (stmt->next() != nullptr) { 555 if (stmt->next() != nullptr) {
444 Visit(stmt->next()); 556 Visit(stmt->next());
445 } 557 }
446 if (stmt->cond()) { 558 if (stmt->cond()) {
447 builder()->Bind(&condition_label); 559 builder()->Bind(&condition_label);
448 Visit(stmt->cond()); 560 VisitForAccumulatorValue(stmt->cond());
449 builder()->JumpIfTrue(&body_label); 561 builder()->JumpIfTrue(&body_label);
450 } else { 562 } else {
451 builder()->Jump(&body_label); 563 builder()->Jump(&body_label);
452 } 564 }
453 builder()->Bind(&done_label); 565 builder()->Bind(&done_label);
454 566
455 loop_builder.SetBreakTarget(done_label); 567 loop_builder.SetBreakTarget(done_label);
456 loop_builder.SetContinueTarget(next_label); 568 loop_builder.SetContinueTarget(next_label);
457 } 569 }
458 570
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 605
494 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { 606 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
495 // Find or build a shared function info. 607 // Find or build a shared function info.
496 Handle<SharedFunctionInfo> shared_info = 608 Handle<SharedFunctionInfo> shared_info =
497 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); 609 Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
498 CHECK(!shared_info.is_null()); // TODO(rmcilroy): Set stack overflow? 610 CHECK(!shared_info.is_null()); // TODO(rmcilroy): Set stack overflow?
499 611
500 builder() 612 builder()
501 ->LoadLiteral(shared_info) 613 ->LoadLiteral(shared_info)
502 .CreateClosure(expr->pretenure() ? TENURED : NOT_TENURED); 614 .CreateClosure(expr->pretenure() ? TENURED : NOT_TENURED);
615 result_scope()->SetResultInAccumulator();
503 } 616 }
504 617
505 618
506 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { 619 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
507 UNIMPLEMENTED(); 620 UNIMPLEMENTED();
508 } 621 }
509 622
510 623
511 void BytecodeGenerator::VisitNativeFunctionLiteral( 624 void BytecodeGenerator::VisitNativeFunctionLiteral(
512 NativeFunctionLiteral* expr) { 625 NativeFunctionLiteral* expr) {
(...skipping 14 matching lines...) Expand all
527 builder()->LoadTrue(); 640 builder()->LoadTrue();
528 } else if (value->IsFalse()) { 641 } else if (value->IsFalse()) {
529 builder()->LoadFalse(); 642 builder()->LoadFalse();
530 } else if (value->IsNull()) { 643 } else if (value->IsNull()) {
531 builder()->LoadNull(); 644 builder()->LoadNull();
532 } else if (value->IsTheHole()) { 645 } else if (value->IsTheHole()) {
533 builder()->LoadTheHole(); 646 builder()->LoadTheHole();
534 } else { 647 } else {
535 builder()->LoadLiteral(value); 648 builder()->LoadLiteral(value);
536 } 649 }
650 result_scope()->SetResultInAccumulator();
537 } 651 }
538 652
539 653
540 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 654 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
541 // Materialize a regular expression literal. 655 // Materialize a regular expression literal.
542 TemporaryRegisterScope temporary_register_scope(builder()); 656 TemporaryRegisterScope temporary_register_scope(builder());
543 Register flags = temporary_register_scope.NewRegister(); 657 Register flags = temporary_register_scope.NewRegister();
544 builder() 658 builder()
545 ->LoadLiteral(expr->flags()) 659 ->LoadLiteral(expr->flags())
546 .StoreAccumulatorInRegister(flags) 660 .StoreAccumulatorInRegister(flags)
547 .LoadLiteral(expr->pattern()) 661 .LoadLiteral(expr->pattern())
548 .CreateRegExpLiteral(expr->literal_index(), flags); 662 .CreateRegExpLiteral(expr->literal_index(), flags);
663 result_scope()->SetResultInAccumulator();
549 } 664 }
550 665
551 666
552 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 667 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
553 // Deep-copy the literal boilerplate. 668 // Deep-copy the literal boilerplate.
554 builder() 669 builder()
555 ->LoadLiteral(expr->constant_properties()) 670 ->LoadLiteral(expr->constant_properties())
556 .CreateObjectLiteral(expr->literal_index(), expr->ComputeFlags(true)); 671 .CreateObjectLiteral(expr->literal_index(), expr->ComputeFlags(true));
557 672
558 TemporaryRegisterScope temporary_register_scope(builder()); 673 TemporaryRegisterScope temporary_register_scope(builder());
(...skipping 24 matching lines...) Expand all
583 // Fall through. 698 // Fall through.
584 case ObjectLiteral::Property::COMPUTED: { 699 case ObjectLiteral::Property::COMPUTED: {
585 // It is safe to use [[Put]] here because the boilerplate already 700 // It is safe to use [[Put]] here because the boilerplate already
586 // contains computed properties with an uninitialized value. 701 // contains computed properties with an uninitialized value.
587 if (literal_key->value()->IsInternalizedString()) { 702 if (literal_key->value()->IsInternalizedString()) {
588 if (property->emit_store()) { 703 if (property->emit_store()) {
589 Register name = inner_temporary_register_scope.NewRegister(); 704 Register name = inner_temporary_register_scope.NewRegister();
590 builder() 705 builder()
591 ->LoadLiteral(literal_key->AsPropertyName()) 706 ->LoadLiteral(literal_key->AsPropertyName())
592 .StoreAccumulatorInRegister(name); 707 .StoreAccumulatorInRegister(name);
593 Visit(property->value()); 708 VisitForAccumulatorValue(property->value());
594 builder()->StoreNamedProperty(literal, name, 709 builder()->StoreNamedProperty(literal, name,
595 feedback_index(property->GetSlot(0)), 710 feedback_index(property->GetSlot(0)),
596 language_mode()); 711 language_mode());
597 } else { 712 } else {
598 Visit(property->value()); 713 VisitForEffect(property->value());
599 } 714 }
600 } else { 715 } else {
601 Register key = inner_temporary_register_scope.NewRegister(); 716 inner_temporary_register_scope.PrepareForConsecutiveAllocations(3);
602 Register value = inner_temporary_register_scope.NewRegister(); 717 Register key =
603 Register language = inner_temporary_register_scope.NewRegister(); 718 inner_temporary_register_scope.NextConsecutiveRegister();
719 Register value =
720 inner_temporary_register_scope.NextConsecutiveRegister();
721 Register language =
722 inner_temporary_register_scope.NextConsecutiveRegister();
723 // TODO(oth): This is problematic - can't assume contiguous here.
724 // literal is allocated in temporary_register_scope, whereas
725 // key, value, language are in another.
rmcilroy 2015/10/20 16:39:20 Hmm, this is tricky. One option would be to do the
oth 2015/10/20 20:58:42 We may have exactly the right mix of allocation sc
604 DCHECK(Register::AreContiguous(literal, key, value, language)); 726 DCHECK(Register::AreContiguous(literal, key, value, language));
605 Visit(property->key()); 727 VisitForAccumulatorValue(property->key());
606 builder()->StoreAccumulatorInRegister(key); 728 builder()->StoreAccumulatorInRegister(key);
607 Visit(property->value()); 729 VisitForAccumulatorValue(property->value());
608 builder()->StoreAccumulatorInRegister(value); 730 builder()->StoreAccumulatorInRegister(value);
609 if (property->emit_store()) { 731 if (property->emit_store()) {
610 builder() 732 builder()
611 ->LoadLiteral(Smi::FromInt(SLOPPY)) 733 ->LoadLiteral(Smi::FromInt(SLOPPY))
612 .StoreAccumulatorInRegister(language) 734 .StoreAccumulatorInRegister(language)
613 .CallRuntime(Runtime::kSetProperty, literal, 4); 735 .CallRuntime(Runtime::kSetProperty, literal, 4);
614 VisitSetHomeObject(value, literal, property); 736 VisitSetHomeObject(value, literal, property);
615 } 737 }
616 } 738 }
617 break; 739 break;
618 } 740 }
619 case ObjectLiteral::Property::PROTOTYPE: { 741 case ObjectLiteral::Property::PROTOTYPE: {
742 inner_temporary_register_scope.PrepareForConsecutiveAllocations(1);
620 DCHECK(property->emit_store()); 743 DCHECK(property->emit_store());
621 Register value = inner_temporary_register_scope.NewRegister(); 744 Register value =
745 inner_temporary_register_scope.NextConsecutiveRegister();
622 DCHECK(Register::AreContiguous(literal, value)); 746 DCHECK(Register::AreContiguous(literal, value));
623 Visit(property->value()); 747 VisitForAccumulatorValue(property->value());
624 builder()->StoreAccumulatorInRegister(value).CallRuntime( 748 builder()->StoreAccumulatorInRegister(value).CallRuntime(
625 Runtime::kInternalSetPrototype, literal, 2); 749 Runtime::kInternalSetPrototype, literal, 2);
626 break; 750 break;
627 } 751 }
628 case ObjectLiteral::Property::GETTER: 752 case ObjectLiteral::Property::GETTER:
629 if (property->emit_store()) { 753 if (property->emit_store()) {
630 accessor_table.lookup(literal_key)->second->getter = property; 754 accessor_table.lookup(literal_key)->second->getter = property;
631 } 755 }
632 break; 756 break;
633 case ObjectLiteral::Property::SETTER: 757 case ObjectLiteral::Property::SETTER:
634 if (property->emit_store()) { 758 if (property->emit_store()) {
635 accessor_table.lookup(literal_key)->second->setter = property; 759 accessor_table.lookup(literal_key)->second->setter = property;
636 } 760 }
637 break; 761 break;
638 } 762 }
639 } 763 }
640 764
641 // Define accessors, using only a single call to the runtime for each pair of 765 // Define accessors, using only a single call to the runtime for each pair of
642 // corresponding getters and setters. 766 // corresponding getters and setters.
643 for (AccessorTable::Iterator it = accessor_table.begin(); 767 for (AccessorTable::Iterator it = accessor_table.begin();
644 it != accessor_table.end(); ++it) { 768 it != accessor_table.end(); ++it) {
645 TemporaryRegisterScope inner_temporary_register_scope(builder()); 769 TemporaryRegisterScope inner_temporary_register_scope(builder());
646 Register name = inner_temporary_register_scope.NewRegister(); 770 inner_temporary_register_scope.PrepareForConsecutiveAllocations(4);
647 Register getter = inner_temporary_register_scope.NewRegister(); 771 Register name = inner_temporary_register_scope.NextConsecutiveRegister();
648 Register setter = inner_temporary_register_scope.NewRegister(); 772 Register getter = inner_temporary_register_scope.NextConsecutiveRegister();
649 Register attr = inner_temporary_register_scope.NewRegister(); 773 Register setter = inner_temporary_register_scope.NextConsecutiveRegister();
774 Register attr = inner_temporary_register_scope.NextConsecutiveRegister();
650 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); 775 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr));
651 Visit(it->first); 776 VisitForAccumulatorValue(it->first);
652 builder()->StoreAccumulatorInRegister(name); 777 builder()->StoreAccumulatorInRegister(name);
653 VisitObjectLiteralAccessor(literal, it->second->getter, getter); 778 VisitObjectLiteralAccessor(literal, it->second->getter, getter);
654 VisitObjectLiteralAccessor(literal, it->second->setter, setter); 779 VisitObjectLiteralAccessor(literal, it->second->setter, setter);
655 builder() 780 builder()
656 ->LoadLiteral(Smi::FromInt(NONE)) 781 ->LoadLiteral(Smi::FromInt(NONE))
657 .StoreAccumulatorInRegister(attr) 782 .StoreAccumulatorInRegister(attr)
658 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5); 783 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5);
659 } 784 }
660 785
661 // Object literals have two parts. The "static" part on the left contains no 786 // Object literals have two parts. The "static" part on the left contains no
662 // computed property names, and so we can compute its map ahead of time; see 787 // computed property names, and so we can compute its map ahead of time; see
663 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts 788 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
664 // with the first computed property name and continues with all properties to 789 // with the first computed property name and continues with all properties to
665 // its right. All the code from above initializes the static component of the 790 // its right. All the code from above initializes the static component of the
666 // object literal, and arranges for the map of the result to reflect the 791 // object literal, and arranges for the map of the result to reflect the
667 // static order in which the keys appear. For the dynamic properties, we 792 // static order in which the keys appear. For the dynamic properties, we
668 // compile them into a series of "SetOwnProperty" runtime calls. This will 793 // compile them into a series of "SetOwnProperty" runtime calls. This will
669 // preserve insertion order. 794 // preserve insertion order.
670 for (; property_index < expr->properties()->length(); property_index++) { 795 for (; property_index < expr->properties()->length(); property_index++) {
671 ObjectLiteral::Property* property = expr->properties()->at(property_index); 796 ObjectLiteral::Property* property = expr->properties()->at(property_index);
672 797
673 if (literal_in_accumulator) { 798 if (literal_in_accumulator) {
674 literal = temporary_register_scope.NewRegister(); 799 temporary_register_scope.PrepareForConsecutiveAllocations(4);
800 literal = temporary_register_scope.NextConsecutiveRegister();
675 builder()->StoreAccumulatorInRegister(literal); 801 builder()->StoreAccumulatorInRegister(literal);
676 literal_in_accumulator = false; 802 literal_in_accumulator = false;
677 } 803 }
678 804
679 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { 805 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
680 DCHECK(property->emit_store()); 806 DCHECK(property->emit_store());
681 TemporaryRegisterScope inner_temporary_register_scope(builder()); 807 TemporaryRegisterScope inner_temporary_register_scope(builder());
682 Register value = inner_temporary_register_scope.NewRegister(); 808 Register value = inner_temporary_register_scope.NewRegister();
683 DCHECK(Register::AreContiguous(literal, value)); 809 DCHECK(Register::AreContiguous(literal, value));
684 Visit(property->value()); 810 VisitForAccumulatorValue(property->value());
685 builder()->StoreAccumulatorInRegister(value).CallRuntime( 811 builder()->StoreAccumulatorInRegister(value).CallRuntime(
686 Runtime::kInternalSetPrototype, literal, 2); 812 Runtime::kInternalSetPrototype, literal, 2);
687 continue; 813 continue;
688 } 814 }
689 815
690 TemporaryRegisterScope inner_temporary_register_scope(builder()); 816 TemporaryRegisterScope inner_temporary_register_scope(builder());
691 Register key = inner_temporary_register_scope.NewRegister(); 817 inner_temporary_register_scope.PrepareForConsecutiveAllocations(3);
692 Register value = inner_temporary_register_scope.NewRegister(); 818 Register key = inner_temporary_register_scope.NextConsecutiveRegister();
693 Register attr = inner_temporary_register_scope.NewRegister(); 819 Register value = inner_temporary_register_scope.NextConsecutiveRegister();
820 Register attr = inner_temporary_register_scope.NextConsecutiveRegister();
694 DCHECK(Register::AreContiguous(literal, key, value, attr)); 821 DCHECK(Register::AreContiguous(literal, key, value, attr));
695 822
696 Visit(property->key()); 823 VisitForAccumulatorValue(property->key());
697 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); 824 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
698 Visit(property->value()); 825 VisitForAccumulatorValue(property->value());
699 builder()->StoreAccumulatorInRegister(value); 826 builder()->StoreAccumulatorInRegister(value);
700 VisitSetHomeObject(value, literal, property); 827 VisitSetHomeObject(value, literal, property);
701 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); 828 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr);
702 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1); 829 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1);
703 switch (property->kind()) { 830 switch (property->kind()) {
704 case ObjectLiteral::Property::CONSTANT: 831 case ObjectLiteral::Property::CONSTANT:
705 case ObjectLiteral::Property::COMPUTED: 832 case ObjectLiteral::Property::COMPUTED:
706 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 833 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
707 function_id = Runtime::kDefineDataPropertyUnchecked; 834 function_id = Runtime::kDefineDataPropertyUnchecked;
708 break; 835 break;
(...skipping 13 matching lines...) Expand all
722 // Transform literals that contain functions to fast properties. 849 // Transform literals that contain functions to fast properties.
723 if (expr->has_function()) { 850 if (expr->has_function()) {
724 DCHECK(!literal_in_accumulator); 851 DCHECK(!literal_in_accumulator);
725 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); 852 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1);
726 } 853 }
727 854
728 if (!literal_in_accumulator) { 855 if (!literal_in_accumulator) {
729 // Restore literal array into accumulator. 856 // Restore literal array into accumulator.
730 builder()->LoadAccumulatorWithRegister(literal); 857 builder()->LoadAccumulatorWithRegister(literal);
731 } 858 }
859 result_scope()->SetResultInAccumulator();
732 } 860 }
733 861
734 862
735 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 863 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
736 // Deep-copy the literal boilerplate. 864 // Deep-copy the literal boilerplate.
737 builder() 865 builder()
738 ->LoadLiteral(expr->constant_elements()) 866 ->LoadLiteral(expr->constant_elements())
739 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true)); 867 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true));
740 868
741 TemporaryRegisterScope temporary_register_scope(builder()); 869 TemporaryRegisterScope temporary_register_scope(builder());
(...skipping 11 matching lines...) Expand all
753 UNIMPLEMENTED(); 881 UNIMPLEMENTED();
754 } 882 }
755 883
756 if (literal_in_accumulator) { 884 if (literal_in_accumulator) {
757 index = temporary_register_scope.NewRegister(); 885 index = temporary_register_scope.NewRegister();
758 literal = temporary_register_scope.NewRegister(); 886 literal = temporary_register_scope.NewRegister();
759 builder()->StoreAccumulatorInRegister(literal); 887 builder()->StoreAccumulatorInRegister(literal);
760 literal_in_accumulator = false; 888 literal_in_accumulator = false;
761 } 889 }
762 890
891 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot();
763 builder() 892 builder()
764 ->LoadLiteral(Smi::FromInt(array_index)) 893 ->LoadLiteral(Smi::FromInt(array_index))
765 .StoreAccumulatorInRegister(index); 894 .StoreAccumulatorInRegister(index);
766 Visit(subexpr); 895 VisitForAccumulatorValue(subexpr);
767 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot();
768 builder()->StoreKeyedProperty(literal, index, feedback_index(slot), 896 builder()->StoreKeyedProperty(literal, index, feedback_index(slot),
769 language_mode()); 897 language_mode());
770 } 898 }
771 899
772 if (!literal_in_accumulator) { 900 if (!literal_in_accumulator) {
773 // Restore literal array into accumulator. 901 // Restore literal array into accumulator.
774 builder()->LoadAccumulatorWithRegister(literal); 902 builder()->LoadAccumulatorWithRegister(literal);
775 } 903 }
904 result_scope()->SetResultInAccumulator();
776 } 905 }
777 906
778 907
779 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { 908 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
780 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 909 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
781 } 910 }
782 911
783 912
784 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 913 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
785 FeedbackVectorSlot slot) { 914 FeedbackVectorSlot slot) {
786 switch (variable->location()) { 915 switch (variable->location()) {
787 case VariableLocation::LOCAL: { 916 case VariableLocation::LOCAL: {
788 Register source(variable->index()); 917 Register source(Register(variable->index()));
789 builder()->LoadAccumulatorWithRegister(source); 918 result_scope()->SetResultInRegister(source);
790 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and
791 // let variables.
792 break; 919 break;
793 } 920 }
794 case VariableLocation::PARAMETER: { 921 case VariableLocation::PARAMETER: {
795 // The parameter indices are shifted by 1 (receiver is variable 922 // The parameter indices are shifted by 1 (receiver is variable
796 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 923 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
797 Register source(builder()->Parameter(variable->index() + 1)); 924 Register source = builder()->Parameter(variable->index() + 1);
798 builder()->LoadAccumulatorWithRegister(source); 925 result_scope()->SetResultInRegister(source);
799 break; 926 break;
800 } 927 }
801 case VariableLocation::GLOBAL: { 928 case VariableLocation::GLOBAL: {
802 // Global var, const, or let variable. 929 // Global var, const, or let variable.
803 // TODO(rmcilroy): If context chain depth is short enough, do this using 930 // TODO(rmcilroy): If context chain depth is short enough, do this using
804 // a generic version of LoadGlobalViaContextStub rather than calling the 931 // a generic version of LoadGlobalViaContextStub rather than calling the
805 // runtime. 932 // runtime.
806 DCHECK(variable->IsStaticGlobalObjectProperty()); 933 DCHECK(variable->IsStaticGlobalObjectProperty());
807 builder()->LoadGlobal(variable->index()); 934 builder()->LoadGlobal(variable->index());
935 result_scope()->SetResultInAccumulator();
808 break; 936 break;
809 } 937 }
810 case VariableLocation::UNALLOCATED: { 938 case VariableLocation::UNALLOCATED: {
811 TemporaryRegisterScope temporary_register_scope(builder()); 939 TemporaryRegisterScope temporary_register_scope(builder());
812 Register obj = temporary_register_scope.NewRegister(); 940 Register obj = temporary_register_scope.NewRegister();
813 builder()->LoadContextSlot(execution_context()->reg(), 941 builder()->LoadContextSlot(execution_context()->reg(),
814 Context::GLOBAL_OBJECT_INDEX); 942 Context::GLOBAL_OBJECT_INDEX);
815 builder()->StoreAccumulatorInRegister(obj); 943 builder()->StoreAccumulatorInRegister(obj);
816 builder()->LoadLiteral(variable->name()); 944 builder()->LoadLiteral(variable->name());
817 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); 945 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode());
946 result_scope()->SetResultInAccumulator();
818 break; 947 break;
819 } 948 }
820 case VariableLocation::CONTEXT: { 949 case VariableLocation::CONTEXT: {
821 ContextScope* context = execution_context()->Previous(variable->scope()); 950 ContextScope* context = execution_context()->Previous(variable->scope());
822 if (context) { 951 if (context) {
823 builder()->LoadContextSlot(context->reg(), variable->index()); 952 builder()->LoadContextSlot(context->reg(), variable->index());
824 } else { 953 } else {
825 UNIMPLEMENTED(); 954 UNIMPLEMENTED();
826 } 955 }
956 result_scope()->SetResultInAccumulator();
827 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and 957 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and
828 // let variables. 958 // let variables.
829 break; 959 break;
830 } 960 }
831 case VariableLocation::LOOKUP: 961 case VariableLocation::LOOKUP:
832 UNIMPLEMENTED(); 962 UNIMPLEMENTED();
833 } 963 }
834 } 964 }
835 965
836 966
837 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 967 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
838 FeedbackVectorSlot slot) { 968 FeedbackVectorSlot slot) {
839 switch (variable->location()) { 969 switch (variable->location()) {
840 case VariableLocation::LOCAL: { 970 case VariableLocation::LOCAL: {
841 // TODO(rmcilroy): support const mode initialization. 971 // TODO(rmcilroy): support const mode initialization.
842 Register destination(variable->index()); 972 Register destination(variable->index());
843 builder()->StoreAccumulatorInRegister(destination); 973 builder()->StoreAccumulatorInRegister(destination);
974 RecordStoreToRegister(destination);
844 break; 975 break;
845 } 976 }
846 case VariableLocation::PARAMETER: { 977 case VariableLocation::PARAMETER: {
847 // The parameter indices are shifted by 1 (receiver is variable 978 // The parameter indices are shifted by 1 (receiver is variable
848 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 979 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
849 Register destination(builder()->Parameter(variable->index() + 1)); 980 Register destination(builder()->Parameter(variable->index() + 1));
850 builder()->StoreAccumulatorInRegister(destination); 981 builder()->StoreAccumulatorInRegister(destination);
982 RecordStoreToRegister(destination);
851 break; 983 break;
852 } 984 }
853 case VariableLocation::GLOBAL: { 985 case VariableLocation::GLOBAL: {
854 // Global var, const, or let variable. 986 // Global var, const, or let variable.
855 // TODO(rmcilroy): If context chain depth is short enough, do this using 987 // TODO(rmcilroy): If context chain depth is short enough, do this using
856 // a generic version of LoadGlobalViaContextStub rather than calling the 988 // a generic version of LoadGlobalViaContextStub rather than calling the
857 // runtime. 989 // runtime.
858 DCHECK(variable->IsStaticGlobalObjectProperty()); 990 DCHECK(variable->IsStaticGlobalObjectProperty());
859 builder()->StoreGlobal(variable->index(), language_mode()); 991 builder()->StoreGlobal(variable->index(), language_mode());
860 break; 992 break;
861 } 993 }
862 case VariableLocation::UNALLOCATED: { 994 case VariableLocation::UNALLOCATED: {
863 TemporaryRegisterScope temporary_register_scope(builder()); 995 Register value = result_scope()->NewRegister();
864 Register value = temporary_register_scope.NewRegister(); 996 Register obj = result_scope()->NewRegister();
865 Register obj = temporary_register_scope.NewRegister(); 997 Register name = result_scope()->NewRegister();
866 Register name = temporary_register_scope.NewRegister(); 998
867 // TODO(rmcilroy): Investigate whether we can avoid having to stash the 999 // TODO(rmcilroy): Investigate whether we can avoid having to stash the
868 // value in a register. 1000 // value in a register.
869 builder()->StoreAccumulatorInRegister(value); 1001 builder()->StoreAccumulatorInRegister(value);
870 builder()->LoadContextSlot(execution_context()->reg(), 1002 builder()->LoadContextSlot(execution_context()->reg(),
871 Context::GLOBAL_OBJECT_INDEX); 1003 Context::GLOBAL_OBJECT_INDEX);
872 builder()->StoreAccumulatorInRegister(obj); 1004 builder()->StoreAccumulatorInRegister(obj);
873 builder()->LoadLiteral(variable->name()); 1005 builder()->LoadLiteral(variable->name());
874 builder()->StoreAccumulatorInRegister(name); 1006 builder()->StoreAccumulatorInRegister(name);
875 builder()->LoadAccumulatorWithRegister(value); 1007 builder()->LoadAccumulatorWithRegister(value);
876 builder()->StoreNamedProperty(obj, name, feedback_index(slot), 1008 builder()->StoreNamedProperty(obj, name, feedback_index(slot),
(...skipping 11 matching lines...) Expand all
888 break; 1020 break;
889 } 1021 }
890 case VariableLocation::LOOKUP: 1022 case VariableLocation::LOOKUP:
891 UNIMPLEMENTED(); 1023 UNIMPLEMENTED();
892 } 1024 }
893 } 1025 }
894 1026
895 1027
896 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 1028 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
897 DCHECK(expr->target()->IsValidReferenceExpression()); 1029 DCHECK(expr->target()->IsValidReferenceExpression());
898 TemporaryRegisterScope temporary_register_scope(builder());
899 Register object, key; 1030 Register object, key;
900 1031
901 // Left-hand side can only be a property, a global or a variable slot. 1032 // Left-hand side can only be a property, a global or a variable slot.
902 Property* property = expr->target()->AsProperty(); 1033 Property* property = expr->target()->AsProperty();
903 LhsKind assign_type = Property::GetAssignType(property); 1034 LhsKind assign_type = Property::GetAssignType(property);
904 1035
905 // Evaluate LHS expression. 1036 // Evaluate LHS expression.
906 switch (assign_type) { 1037 switch (assign_type) {
907 case VARIABLE: 1038 case VARIABLE:
908 // Nothing to do to evaluate variable assignment LHS. 1039 // Nothing to do to evaluate variable assignment LHS.
909 break; 1040 break;
910 case NAMED_PROPERTY: 1041 case NAMED_PROPERTY: {
911 object = temporary_register_scope.NewRegister(); 1042 object = VisitForRegisterValue(property->obj());
912 key = temporary_register_scope.NewRegister(); 1043 key = result_scope()->NewRegister();
913 Visit(property->obj());
914 builder()->StoreAccumulatorInRegister(object);
915 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()); 1044 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName());
916 builder()->StoreAccumulatorInRegister(key); 1045 builder()->StoreAccumulatorInRegister(key);
917 break; 1046 break;
918 case KEYED_PROPERTY: 1047 }
919 object = temporary_register_scope.NewRegister(); 1048 case KEYED_PROPERTY: {
920 key = temporary_register_scope.NewRegister(); 1049 object = VisitForRegisterValue(property->obj());
921 Visit(property->obj()); 1050 key = VisitForRegisterValue(property->key());
922 builder()->StoreAccumulatorInRegister(object);
923 Visit(property->key());
924 builder()->StoreAccumulatorInRegister(key);
925 break; 1051 break;
1052 }
926 case NAMED_SUPER_PROPERTY: 1053 case NAMED_SUPER_PROPERTY:
927 case KEYED_SUPER_PROPERTY: 1054 case KEYED_SUPER_PROPERTY:
928 UNIMPLEMENTED(); 1055 UNIMPLEMENTED();
929 } 1056 }
930 1057
931 // Evaluate the value and potentially handle compound assignments by loading 1058 // Evaluate the value and potentially handle compound assignments by loading
932 // the left-hand side value and performing a binary operation. 1059 // the left-hand side value and performing a binary operation.
933 if (expr->is_compound()) { 1060 if (expr->is_compound()) {
934 UNIMPLEMENTED(); 1061 UNIMPLEMENTED();
935 } else { 1062 } else {
936 Visit(expr->value()); 1063 VisitForAccumulatorValue(expr->value());
1064 result_scope()->SetResultInAccumulator();
937 } 1065 }
938 1066
939 // Store the value. 1067 // Store the value.
940 FeedbackVectorSlot slot = expr->AssignmentSlot(); 1068 FeedbackVectorSlot slot = expr->AssignmentSlot();
941 switch (assign_type) { 1069 switch (assign_type) {
942 case VARIABLE: { 1070 case VARIABLE: {
943 Variable* variable = expr->target()->AsVariableProxy()->var(); 1071 Variable* variable = expr->target()->AsVariableProxy()->var();
944 VisitVariableAssignment(variable, slot); 1072 VisitVariableAssignment(variable, slot);
945 break; 1073 break;
946 } 1074 }
(...skipping 20 matching lines...) Expand all
967 1095
968 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { 1096 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
969 LhsKind property_kind = Property::GetAssignType(expr); 1097 LhsKind property_kind = Property::GetAssignType(expr);
970 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); 1098 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
971 switch (property_kind) { 1099 switch (property_kind) {
972 case VARIABLE: 1100 case VARIABLE:
973 UNREACHABLE(); 1101 UNREACHABLE();
974 case NAMED_PROPERTY: { 1102 case NAMED_PROPERTY: {
975 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName()); 1103 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName());
976 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); 1104 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode());
1105 result_scope()->SetResultInAccumulator();
977 break; 1106 break;
978 } 1107 }
979 case KEYED_PROPERTY: { 1108 case KEYED_PROPERTY: {
980 Visit(expr->key()); 1109 VisitForAccumulatorValue(expr->key());
981 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode()); 1110 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode());
1111 result_scope()->SetResultInAccumulator();
982 break; 1112 break;
983 } 1113 }
984 case NAMED_SUPER_PROPERTY: 1114 case NAMED_SUPER_PROPERTY:
985 case KEYED_SUPER_PROPERTY: 1115 case KEYED_SUPER_PROPERTY:
986 UNIMPLEMENTED(); 1116 UNIMPLEMENTED();
987 } 1117 }
988 } 1118 }
989 1119
990 1120
991 void BytecodeGenerator::VisitProperty(Property* expr) { 1121 void BytecodeGenerator::VisitProperty(Property* expr) {
992 TemporaryRegisterScope temporary_register_scope(builder()); 1122 Register obj = VisitForRegisterValue(expr->obj());
993 Register obj = temporary_register_scope.NewRegister();
994 Visit(expr->obj());
995 builder()->StoreAccumulatorInRegister(obj);
996 VisitPropertyLoad(obj, expr); 1123 VisitPropertyLoad(obj, expr);
997 } 1124 }
998 1125
999 1126
1000 Register BytecodeGenerator::VisitArguments( 1127 Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) {
1001 ZoneList<Expression*>* args, TemporaryRegisterScope* register_scope) {
1002 // Visit arguments and place in a contiguous block of temporary registers. 1128 // Visit arguments and place in a contiguous block of temporary registers.
1003 // Return the first temporary register corresponding to the first argument. 1129 // Return the first temporary register corresponding to the first argument.
1004 DCHECK_GT(args->length(), 0); 1130 result_scope()->PrepareForConsecutiveAllocations(args->length());
1005 Register first_arg = register_scope->NewRegister(); 1131
1006 Visit(args->at(0)); 1132 // Visit for first argument that goes into returned register
1133 Register first_arg = result_scope()->NextConsecutiveRegister();
1134 VisitForAccumulatorValue(args->at(0));
1007 builder()->StoreAccumulatorInRegister(first_arg); 1135 builder()->StoreAccumulatorInRegister(first_arg);
1136
1137 // Visit remaining arguments
1008 for (int i = 1; i < static_cast<int>(args->length()); i++) { 1138 for (int i = 1; i < static_cast<int>(args->length()); i++) {
1009 Register ith_arg = register_scope->NewRegister(); 1139 Register ith_arg = result_scope()->NextConsecutiveRegister();
1010 Visit(args->at(i)); 1140 VisitForAccumulatorValue(args->at(i));
1011 builder()->StoreAccumulatorInRegister(ith_arg); 1141 builder()->StoreAccumulatorInRegister(ith_arg);
1012 DCHECK(ith_arg.index() - i == first_arg.index()); 1142 DCHECK(ith_arg.index() - i == first_arg.index());
1013 } 1143 }
1014
1015 return first_arg; 1144 return first_arg;
1016 } 1145 }
1017 1146
1018 1147
1019 void BytecodeGenerator::VisitCall(Call* expr) { 1148 void BytecodeGenerator::VisitCall(Call* expr) {
1020 Expression* callee_expr = expr->expression(); 1149 Expression* callee_expr = expr->expression();
1021 Call::CallType call_type = expr->GetCallType(isolate()); 1150 Call::CallType call_type = expr->GetCallType(isolate());
1022 1151
1023 // Prepare the callee and the receiver to the function call. This depends on 1152 // Prepare the callee and the receiver to the function call. This depends on
1024 // the semantics of the underlying call type. 1153 // the semantics of the underlying call type.
1025 TemporaryRegisterScope temporary_register_scope(builder()); 1154 Register callee = result_scope()->NewRegister();
1026 Register callee = temporary_register_scope.NewRegister(); 1155
1027 Register receiver = temporary_register_scope.NewRegister(); 1156 // The receiver and arguments need to be allocated consecutively for
1157 // Call(). Future optimizations could avoid this there are no
1158 // arguments or the receiver and arguments are already consecutive.
1159 ZoneList<Expression*>* args = expr->arguments();
1160 result_scope()->PrepareForConsecutiveAllocations(args->length() + 1);
rmcilroy 2015/10/20 16:39:20 You call PrepareForConsecutiveAllocations(args->le
oth 2015/10/20 20:58:42 Comment added to VisitArguments. The weirdness is
1161 Register receiver = result_scope()->NextConsecutiveRegister();
1028 1162
1029 switch (call_type) { 1163 switch (call_type) {
1030 case Call::PROPERTY_CALL: { 1164 case Call::PROPERTY_CALL: {
1031 Property* property = callee_expr->AsProperty(); 1165 Property* property = callee_expr->AsProperty();
1032 if (property->IsSuperAccess()) { 1166 if (property->IsSuperAccess()) {
1033 UNIMPLEMENTED(); 1167 UNIMPLEMENTED();
1034 } 1168 }
1035 Visit(property->obj()); 1169 VisitForAccumulatorValue(property->obj());
1036 builder()->StoreAccumulatorInRegister(receiver); 1170 builder()->StoreAccumulatorInRegister(receiver);
1171 // Need a result scope here to keep our consecutive
1172 // temporaries.
1173 AccumulatorResultScope accumulator_result_scope(this);
1037 // Perform a property load of the callee. 1174 // Perform a property load of the callee.
1038 VisitPropertyLoad(receiver, property); 1175 VisitPropertyLoad(receiver, property);
1039 builder()->StoreAccumulatorInRegister(callee); 1176 builder()->StoreAccumulatorInRegister(callee);
1040 break; 1177 break;
1041 } 1178 }
1042 case Call::GLOBAL_CALL: { 1179 case Call::GLOBAL_CALL: {
1180 AccumulatorResultScope accumulator_result_scope(this);
rmcilroy 2015/10/20 16:39:20 Not sure why this is needed? Could you add a comme
oth 2015/10/20 20:58:42 Comment added and scope moved immediately before V
1043 // Receiver is undefined for global calls. 1181 // Receiver is undefined for global calls.
1044 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); 1182 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
1045 // Load callee as a global variable. 1183 // Load callee as a global variable.
1046 VariableProxy* proxy = callee_expr->AsVariableProxy(); 1184 VariableProxy* proxy = callee_expr->AsVariableProxy();
1047 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 1185 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1048 builder()->StoreAccumulatorInRegister(callee); 1186 builder()->StoreAccumulatorInRegister(callee);
1049 break; 1187 break;
1050 } 1188 }
1051 case Call::OTHER_CALL: { 1189 case Call::OTHER_CALL: {
1052 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); 1190 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
1053 Visit(callee_expr); 1191 VisitForAccumulatorValue(callee_expr);
1054 builder()->StoreAccumulatorInRegister(callee); 1192 builder()->StoreAccumulatorInRegister(callee);
1055 break; 1193 break;
1056 } 1194 }
1057 case Call::LOOKUP_SLOT_CALL: 1195 case Call::LOOKUP_SLOT_CALL:
1058 case Call::SUPER_CALL: 1196 case Call::SUPER_CALL:
1059 case Call::POSSIBLY_EVAL_CALL: 1197 case Call::POSSIBLY_EVAL_CALL:
1060 UNIMPLEMENTED(); 1198 UNIMPLEMENTED();
1061 } 1199 }
1062 1200
1063 // Evaluate all arguments to the function call and store in sequential 1201 // Evaluate all arguments to the function call and store in sequential
1064 // registers. 1202 // registers.
1065 ZoneList<Expression*>* args = expr->arguments();
1066 if (args->length() > 0) { 1203 if (args->length() > 0) {
1067 Register first_arg = VisitArguments(args, &temporary_register_scope); 1204 Register arg = VisitArguments(args);
1068 CHECK_EQ(first_arg.index(), receiver.index() + 1); 1205 CHECK(arg.index() == receiver.index() + 1);
1069 } 1206 }
1070 1207
1071 // TODO(rmcilroy): Deal with possible direct eval here? 1208 // TODO(rmcilroy): Deal with possible direct eval here?
1072 // TODO(rmcilroy): Use CallIC to allow call type feedback. 1209 // TODO(rmcilroy): Use CallIC to allow call type feedback.
1073 builder()->Call(callee, receiver, args->length()); 1210 builder()->Call(callee, receiver, args->length());
1211 result_scope()->SetResultInAccumulator();
1074 } 1212 }
1075 1213
1076 1214
1077 void BytecodeGenerator::VisitCallNew(CallNew* expr) { 1215 void BytecodeGenerator::VisitCallNew(CallNew* expr) {
1078 TemporaryRegisterScope temporary_register_scope(builder()); 1216 Register constructor = result_scope()->NewRegister();
1079 Register constructor = temporary_register_scope.NewRegister(); 1217 VisitForAccumulatorValue(expr->expression());
1080 Visit(expr->expression());
1081 builder()->StoreAccumulatorInRegister(constructor); 1218 builder()->StoreAccumulatorInRegister(constructor);
1219
1082 ZoneList<Expression*>* args = expr->arguments(); 1220 ZoneList<Expression*>* args = expr->arguments();
1083 if (args->length() > 0) { 1221 if (args->length() > 0) {
1084 Register first_arg = VisitArguments(args, &temporary_register_scope); 1222 Register first_arg = VisitArguments(args);
1085 builder()->New(constructor, first_arg, args->length()); 1223 builder()->New(constructor, first_arg, args->length());
1086 } else { 1224 } else {
1087 // The second argument here will be ignored as there are zero 1225 // The second argument here will be ignored as there are zero
1088 // arguments. Using the constructor register avoids avoid 1226 // arguments. Using the constructor register avoids avoid
1089 // allocating a temporary just to fill the operands. 1227 // allocating a temporary just to fill the operands.
1090 builder()->New(constructor, constructor, 0); 1228 builder()->New(constructor, constructor, 0);
1091 } 1229 }
1230
1231 result_scope()->SetResultInAccumulator();
1092 } 1232 }
1093 1233
1094 1234
1095 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { 1235 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
1096 if (expr->is_jsruntime()) { 1236 if (expr->is_jsruntime()) {
1097 UNIMPLEMENTED(); 1237 UNIMPLEMENTED();
1098 } 1238 }
1099 1239
1100 // Evaluate all arguments to the runtime call.
1101 TemporaryRegisterScope temporary_register_scope(&builder_);
1102
1103 // TODO(rmcilroy): support multiple return values. 1240 // TODO(rmcilroy): support multiple return values.
1104 DCHECK_LE(expr->function()->result_size, 1); 1241 DCHECK_LE(expr->function()->result_size, 1);
1105 Runtime::FunctionId function_id = expr->function()->function_id; 1242 Runtime::FunctionId function_id = expr->function()->function_id;
1243
1244 // Evaluate all arguments to the runtime call.
1106 ZoneList<Expression*>* args = expr->arguments(); 1245 ZoneList<Expression*>* args = expr->arguments();
1107 Register first_arg; 1246 Register first_arg;
1108 if (args->length() > 0) { 1247 if (args->length() > 0) {
1109 first_arg = VisitArguments(args, &temporary_register_scope); 1248 first_arg = VisitArguments(args);
1110 } else { 1249 } else {
1111 // Allocation here is just to fullfil the requirement that there 1250 // Allocation here is just to fullfil the requirement that there
1112 // is a register operand for the start of the arguments though 1251 // is a register operand for the start of the arguments though
1113 // there are zero when this is generated. 1252 // there are zero when this is generated.
1114 first_arg = temporary_register_scope.NewRegister(); 1253 first_arg = result_scope()->NewRegister();
1115 } 1254 }
1116 builder()->CallRuntime(function_id, first_arg, args->length()); 1255 builder()->CallRuntime(function_id, first_arg, args->length());
1256 result_scope()->SetResultInAccumulator();
1117 } 1257 }
1118 1258
1119 1259
1120 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { 1260 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
1121 Visit(expr->expression()); 1261 VisitForEffect(expr->expression());
1122 builder()->LoadUndefined(); 1262 builder()->LoadUndefined();
1263 result_scope()->SetResultInAccumulator();
1123 } 1264 }
1124 1265
1125 1266
1126 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { 1267 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
1127 Visit(expr->expression()); 1268 VisitForAccumulatorValue(expr->expression());
1128 builder()->TypeOf(); 1269 builder()->TypeOf();
1270 result_scope()->SetResultInAccumulator();
1129 } 1271 }
1130 1272
1131 1273
1132 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { 1274 void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
1133 Visit(expr->expression()); 1275 VisitForAccumulatorValue(expr->expression());
1134 builder()->LogicalNot(); 1276 builder()->LogicalNot();
1277 result_scope()->SetResultInAccumulator();
1135 } 1278 }
1136 1279
1137 1280
1138 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 1281 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1139 switch (expr->op()) { 1282 switch (expr->op()) {
1140 case Token::Value::NOT: 1283 case Token::Value::NOT:
1141 VisitNot(expr); 1284 VisitNot(expr);
1142 break; 1285 break;
1143 case Token::Value::TYPEOF: 1286 case Token::Value::TYPEOF:
1144 VisitTypeOf(expr); 1287 VisitTypeOf(expr);
(...skipping 27 matching lines...) Expand all
1172 VisitLogicalAndExpression(binop); 1315 VisitLogicalAndExpression(binop);
1173 break; 1316 break;
1174 default: 1317 default:
1175 VisitArithmeticExpression(binop); 1318 VisitArithmeticExpression(binop);
1176 break; 1319 break;
1177 } 1320 }
1178 } 1321 }
1179 1322
1180 1323
1181 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1324 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1182 Token::Value op = expr->op(); 1325 // TODO(oth): add binary operation scope here to replace
rmcilroy 2015/10/20 16:39:20 As mentioned in the previous review, I don't think
oth 2015/10/20 20:58:42 Done - grumble, grumble :-) We can go conservative
1183 Expression* left = expr->left(); 1326 // {Prepare|Complete}BinaryExpression. This will maintain a counter in the
1184 Expression* right = expr->right(); 1327 // statement or top-level expression scope.
1185 1328 PrepareForBinaryExpression();
1186 TemporaryRegisterScope temporary_register_scope(builder()); 1329 Register lhs = VisitForRegisterValue(expr->left());
1187 Register temporary = temporary_register_scope.NewRegister(); 1330 if (builder()->RegisterIsParameterOrLocal(lhs)) {
1188 1331 // Result was returned in an existing local or parameter. See if
1189 Visit(left); 1332 // it needs to be moved to a temporary.
1190 builder()->StoreAccumulatorInRegister(temporary); 1333 // TODO(oth) LoadFromAliasedRegister call into VisitVariableLoad().
1191 Visit(right); 1334 lhs = LoadFromAliasedRegister(lhs);
1192 builder()->CompareOperation(op, temporary, language_mode_strength()); 1335 }
1336 VisitForAccumulatorValue(expr->right());
1337 builder()->CompareOperation(expr->op(), lhs, language_mode_strength());
1338 result_scope()->SetResultInAccumulator();
1339 CompleteBinaryExpression();
1193 } 1340 }
1194 1341
1195 1342
1343 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
1344 // TODO(oth): add binary operation scope here to replace
1345 // {Prepare|Complete}BinaryExpression. This will maintain a counter in the
1346 // statement or top-level expression scope.
rmcilroy 2015/10/20 16:39:20 ditto
oth 2015/10/20 20:58:42 Done.
1347 PrepareForBinaryExpression();
1348 Register lhs = VisitForRegisterValue(expr->left());
1349 if (builder()->RegisterIsParameterOrLocal(lhs)) {
1350 // Result was returned in an existing local or parameter. See if
1351 // it needs to be moved to a temporary.
1352 // TODO(oth) LoadFromAliasedRegister call into VisitVariableLoad().
1353 lhs = LoadFromAliasedRegister(lhs);
1354 }
1355 VisitForAccumulatorValue(expr->right());
1356 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength());
1357 result_scope()->SetResultInAccumulator();
1358 CompleteBinaryExpression();
1359 }
1360
1361
1196 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } 1362 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
1197 1363
1198 1364
1199 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { 1365 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
1200 UNREACHABLE(); 1366 UNREACHABLE();
1201 } 1367 }
1202 1368
1203 1369
1204 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { 1370 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
1205 UNIMPLEMENTED(); 1371 UNIMPLEMENTED();
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 builder() 1440 builder()
1275 ->LoadLiteral(scope->GetScopeInfo(isolate())) 1441 ->LoadLiteral(scope->GetScopeInfo(isolate()))
1276 .StoreAccumulatorInRegister(scope_info); 1442 .StoreAccumulatorInRegister(scope_info);
1277 VisitFunctionClosureForContext(); 1443 VisitFunctionClosureForContext();
1278 builder() 1444 builder()
1279 ->StoreAccumulatorInRegister(closure) 1445 ->StoreAccumulatorInRegister(closure)
1280 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2); 1446 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2);
1281 } 1447 }
1282 1448
1283 1449
1284 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) {
1285 Token::Value op = binop->op();
1286 Expression* left = binop->left();
1287 Expression* right = binop->right();
1288
1289 TemporaryRegisterScope temporary_register_scope(builder());
1290 Register temporary = temporary_register_scope.NewRegister();
1291
1292 Visit(left);
1293 builder()->StoreAccumulatorInRegister(temporary);
1294 Visit(right);
1295 builder()->BinaryOperation(op, temporary, language_mode_strength());
1296 }
1297
1298
1299 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { 1450 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
1300 Expression* left = binop->left(); 1451 VisitForEffect(binop->left());
1301 Expression* right = binop->right(); 1452 Visit(binop->right());
1302
1303 Visit(left);
1304 Visit(right);
1305 } 1453 }
1306 1454
1307 1455
1308 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { 1456 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
1309 Expression* left = binop->left(); 1457 Expression* left = binop->left();
1310 Expression* right = binop->right(); 1458 Expression* right = binop->right();
1311 1459
1312 // Short-circuit evaluation- If it is known that left is always true, 1460 // Short-circuit evaluation- If it is known that left is always true,
1313 // no need to visit right 1461 // no need to visit right
1314 if (left->ToBooleanIsTrue()) { 1462 if (left->ToBooleanIsTrue()) {
1315 Visit(left); 1463 VisitForAccumulatorValue(left);
1316 } else { 1464 } else {
1317 BytecodeLabel end_label; 1465 BytecodeLabel end_label;
1318 1466 VisitForAccumulatorValue(left);
1319 Visit(left);
1320 builder()->JumpIfToBooleanTrue(&end_label); 1467 builder()->JumpIfToBooleanTrue(&end_label);
1321 Visit(right); 1468 VisitForAccumulatorValue(right);
1322 builder()->Bind(&end_label); 1469 builder()->Bind(&end_label);
1323 } 1470 }
1471 result_scope()->SetResultInAccumulator();
1324 } 1472 }
1325 1473
1326 1474
1327 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { 1475 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
1328 Expression* left = binop->left(); 1476 Expression* left = binop->left();
1329 Expression* right = binop->right(); 1477 Expression* right = binop->right();
1330 1478
1331 // Short-circuit evaluation- If it is known that left is always false, 1479 // Short-circuit evaluation- If it is known that left is always false,
1332 // no need to visit right 1480 // no need to visit right
1333 if (left->ToBooleanIsFalse()) { 1481 if (left->ToBooleanIsFalse()) {
1334 Visit(left); 1482 VisitForAccumulatorValue(left);
1335 } else { 1483 } else {
1336 BytecodeLabel end_label; 1484 BytecodeLabel end_label;
1337 1485 VisitForAccumulatorValue(left);
1338 Visit(left);
1339 builder()->JumpIfToBooleanFalse(&end_label); 1486 builder()->JumpIfToBooleanFalse(&end_label);
1340 Visit(right); 1487 VisitForAccumulatorValue(right);
1341 builder()->Bind(&end_label); 1488 builder()->Bind(&end_label);
1342 } 1489 }
1490 result_scope()->SetResultInAccumulator();
1343 } 1491 }
1344 1492
1345 1493
1346 void BytecodeGenerator::VisitObjectLiteralAccessor( 1494 void BytecodeGenerator::VisitObjectLiteralAccessor(
1347 Register home_object, ObjectLiteralProperty* property, Register value_out) { 1495 Register home_object, ObjectLiteralProperty* property, Register value_out) {
1348 // TODO(rmcilroy): Replace value_out with VisitForRegister(); 1496 // TODO(rmcilroy): Replace value_out with VisitForRegister();
1349 if (property == nullptr) { 1497 if (property == nullptr) {
1350 builder()->LoadNull().StoreAccumulatorInRegister(value_out); 1498 builder()->LoadNull().StoreAccumulatorInRegister(value_out);
1351 } else { 1499 } else {
1352 Visit(property->value()); 1500 VisitForAccumulatorValue(property->value());
1353 builder()->StoreAccumulatorInRegister(value_out); 1501 builder()->StoreAccumulatorInRegister(value_out);
1354 VisitSetHomeObject(value_out, home_object, property); 1502 VisitSetHomeObject(value_out, home_object, property);
1355 } 1503 }
1356 } 1504 }
1357 1505
1358 1506
1359 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, 1507 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
1360 ObjectLiteralProperty* property, 1508 ObjectLiteralProperty* property,
1361 int slot_number) { 1509 int slot_number) {
1362 Expression* expr = property->value(); 1510 Expression* expr = property->value();
(...skipping 23 matching lines...) Expand all
1386 // their closure, not the anonymous closure containing the global code. 1534 // their closure, not the anonymous closure containing the global code.
1387 // Pass a SMI sentinel and let the runtime look up the empty function. 1535 // Pass a SMI sentinel and let the runtime look up the empty function.
1388 builder()->LoadLiteral(Smi::FromInt(0)); 1536 builder()->LoadLiteral(Smi::FromInt(0));
1389 } else { 1537 } else {
1390 DCHECK(closure_scope->is_function_scope()); 1538 DCHECK(closure_scope->is_function_scope());
1391 builder()->LoadAccumulatorWithRegister(Register::function_closure()); 1539 builder()->LoadAccumulatorWithRegister(Register::function_closure());
1392 } 1540 }
1393 } 1541 }
1394 1542
1395 1543
1544 void BytecodeGenerator::PrepareForBinaryExpression() {
1545 if (binary_expression_depth_++ == 0) {
1546 binary_expression_hazard_set_.clear();
1547 }
1548 }
1549
1550
1551 // Visits the expression |expr| and places the result in the accumulator.
1552 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
1553 AccumulatorResultScope accumulator_scope(this);
1554 Visit(expr);
1555 }
1556
1557
1558 // Visits the expression |expr| and discards the result.
1559 void BytecodeGenerator::VisitForEffect(Expression* expr) {
1560 EffectResultScope effect_scope(this);
1561 Visit(expr);
1562 }
1563
1564
1565 // Visits the expression |expr| and places the result in |temporary_register|
1566 // if the result is not already a register value. The return value is
1567 // the register containing the result. The caller should check whether
1568 // this is the temporary register and consider releasing the temporary
1569 // register if not.
rmcilroy 2015/10/20 16:39:20 Comment now out of date (no need to release tempor
oth 2015/10/20 20:58:42 Done.
1570 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
1571 RegisterResultScope register_scope(this);
1572 Visit(expr);
1573 return register_scope.ResultRegister();
1574 }
1575
1576
1577 Register BytecodeGenerator::LoadFromAliasedRegister(Register reg) {
1578 // TODO(oth): Follow on CL to load from re-map here.
1579 DCHECK(builder()->RegisterIsParameterOrLocal(reg));
1580 if (binary_expression_depth_ > 0) {
1581 binary_expression_hazard_set_.insert(reg.index());
1582 }
1583 return reg;
1584 }
1585
1586
1587 void BytecodeGenerator::RecordStoreToRegister(Register reg) {
1588 DCHECK(builder()->RegisterIsParameterOrLocal(reg));
1589 if (binary_expression_depth_ > 0) {
1590 // TODO(oth): a store to a register that's be loaded needs to be
1591 // remapped.
1592 DCHECK(binary_expression_hazard_set_.find(reg.index()) ==
1593 binary_expression_hazard_set_.end());
1594 }
1595 }
1596
1597
1598 void BytecodeGenerator::CompleteBinaryExpression() {
1599 DCHECK(binary_expression_depth_ > 0);
1600 binary_expression_depth_ -= 1;
1601 // TODO(oth): spill remapped registers into origins.
1602 // TODO(oth): make statement/top-level.
1603 }
1604
1605
1396 Register BytecodeGenerator::NextContextRegister() const { 1606 Register BytecodeGenerator::NextContextRegister() const {
1397 if (execution_context() == nullptr) { 1607 if (execution_context() == nullptr) {
1398 // Return the incoming function context for the outermost execution context. 1608 // Return the incoming function context for the outermost execution context.
1399 return Register::function_context(); 1609 return Register::function_context();
1400 } 1610 }
1401 Register previous = execution_context()->reg(); 1611 Register previous = execution_context()->reg();
1402 if (previous == Register::function_context()) { 1612 if (previous == Register::function_context()) {
1403 // If the previous context was the incoming function context, then the next 1613 // If the previous context was the incoming function context, then the next
1404 // context register is the first local context register. 1614 // context register is the first local context register.
1405 return builder_.first_context_register(); 1615 return builder_.first_context_register();
(...skipping 15 matching lines...) Expand all
1421 } 1631 }
1422 1632
1423 1633
1424 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 1634 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
1425 return info()->feedback_vector()->GetIndex(slot); 1635 return info()->feedback_vector()->GetIndex(slot);
1426 } 1636 }
1427 1637
1428 } // namespace interpreter 1638 } // namespace interpreter
1429 } // namespace internal 1639 } // namespace internal
1430 } // namespace v8 1640 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698