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

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