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

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

Powered by Google App Engine
This is Rietveld 408576698