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

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

Powered by Google App Engine
This is Rietveld 408576698