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

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: Update comment in BytecodeGenerator::VisitCall(). 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> 7 #include <stack>
8 8
9 #include "src/compiler.h" 9 #include "src/compiler.h"
10 #include "src/interpreter/control-flow-builders.h" 10 #include "src/interpreter/control-flow-builders.h"
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 Statement* statement) { 82 Statement* statement) {
83 ControlScope* current = this; 83 ControlScope* current = this;
84 do { 84 do {
85 if (current->Execute(command, statement)) return; 85 if (current->Execute(command, statement)) return;
86 current = current->outer(); 86 current = current->outer();
87 } while (current != nullptr); 87 } while (current != nullptr);
88 UNREACHABLE(); 88 UNREACHABLE();
89 } 89 }
90 90
91 91
92 // Scoped base class for determining where the result of an expression
93 // is stored.
94 class BytecodeGenerator::ExpressionResultScope {
95 public:
96 explicit ExpressionResultScope(BytecodeGenerator* generator)
97 : generator_(generator),
98 outer_(generator->result_scope()),
99 result_identified_(false) {
100 generator_->set_result_scope(this);
101 }
102
103 virtual ~ExpressionResultScope() {
104 generator_->set_result_scope(outer_);
105 DCHECK_EQ(result_identified(), true);
106 }
107
108 virtual void SetResultInAccumulator() = 0;
109 virtual void SetResultInRegister(Register reg) = 0;
110
111 BytecodeGenerator* generator() const { return generator_; }
112 BytecodeArrayBuilder* builder() const { return generator()->builder(); }
113
114 protected:
115 void set_result_identified() {
116 DCHECK(!result_identified());
117 result_identified_ = true;
118 }
119 bool result_identified() const { return result_identified_; }
120
121 private:
122 BytecodeGenerator* generator_;
123 ExpressionResultScope* outer_;
124 bool result_identified_;
125 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
126 };
127
128
129 // Scoped class used when the result of the current expression to be
130 // evaluated should go into the interpreter's accumulator register.
131 class BytecodeGenerator::AccumulatorResultScope final
132 : public ExpressionResultScope {
133 public:
134 explicit AccumulatorResultScope(BytecodeGenerator* generator)
135 : ExpressionResultScope(generator) {}
136 virtual void SetResultInAccumulator() {
137 if (!result_identified()) {
138 // TODO(oth): REVIEW.
139 set_result_identified();
140 }
141 }
142 virtual void SetResultInRegister(Register reg) {
143 builder()->LoadAccumulatorWithRegister(reg);
144 set_result_identified();
145 }
146 };
147
148
149 // Scoped class used when the result of the current expression is not
150 // expected to produce a result.
151 class BytecodeGenerator::EffectResultScope final
152 : public ExpressionResultScope {
153 public:
154 explicit EffectResultScope(BytecodeGenerator* generator)
155 : ExpressionResultScope(generator) { set_result_identified(); }
156 virtual void SetResultInAccumulator() {}
157 virtual void SetResultInRegister(Register reg) {}
158 };
159
160
161 // Scoped class used when the result of the current expression to be
162 // evaluated should go into an interpreter register.
163 class BytecodeGenerator::RegisterResultScope final
164 : public ExpressionResultScope {
165 public:
166 explicit RegisterResultScope(BytecodeGenerator* generator,
167 TemporaryRegisterScope* register_scope)
168 : ExpressionResultScope(generator), register_scope_(register_scope) {
169 DCHECK(generator->ResultRegisterIsEmpty());
170 }
171 ~RegisterResultScope() { DCHECK(generator()->ResultRegisterIsEmpty()); }
172
173 virtual void SetResultInAccumulator() {
174 Register allocated = register_scope_->NewRegister();
175 builder()->StoreAccumulatorInRegister(allocated);
176 generator()->SetResultRegister(allocated);
177 set_result_identified();
178 }
179
180 virtual void SetResultInRegister(Register reg) {
181 generator()->SetResultRegister(reg);
182 set_result_identified();
183 }
184
185 private:
186 TemporaryRegisterScope* register_scope_;
187 };
188
189
92 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) 190 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
93 : builder_(isolate, zone), 191 : builder_(isolate, zone),
94 info_(nullptr), 192 info_(nullptr),
95 scope_(nullptr), 193 scope_(nullptr),
96 globals_(0, zone), 194 globals_(0, zone),
97 control_scope_(nullptr), 195 control_scope_(nullptr),
98 current_context_(Register::function_context()) { 196 current_context_(Register::function_context()),
197 result_scope_(nullptr),
198 result_register_(Nothing<Register>()) {
99 InitializeAstVisitor(isolate, zone); 199 InitializeAstVisitor(isolate, zone);
100 } 200 }
101 201
102 202
103 BytecodeGenerator::~BytecodeGenerator() {} 203 BytecodeGenerator::~BytecodeGenerator() {}
104 204
105 205
106 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { 206 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
107 set_info(info); 207 set_info(info);
108 set_scope(info->scope()); 208 set_scope(info->scope());
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); 328 builder()->LoadLiteral(Smi::FromInt(encoded_flags));
229 builder()->StoreAccumulatorInRegister(flags); 329 builder()->StoreAccumulatorInRegister(flags);
230 DCHECK(flags.index() == pairs.index() + 1); 330 DCHECK(flags.index() == pairs.index() + 1);
231 331
232 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); 332 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2);
233 globals()->clear(); 333 globals()->clear();
234 } 334 }
235 335
236 336
237 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 337 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
238 Visit(stmt->expression()); 338 VisitForAccumulatorValue(stmt->expression());
239 } 339 }
240 340
241 341
242 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 342 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
243 // TODO(oth): For control-flow it could be useful to signal empty paths here. 343 // TODO(oth): For control-flow it could be useful to signal empty paths here.
244 } 344 }
245 345
246 346
247 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { 347 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
248 // TODO(oth): Spot easy cases where there code would not need to 348 // TODO(oth): Spot easy cases where there code would not need to
249 // emit the then block or the else block, e.g. condition is 349 // emit the then block or the else block, e.g. condition is
250 // obviously true/1/false/0. 350 // obviously true/1/false/0.
251 351
252 BytecodeLabel else_label, end_label; 352 BytecodeLabel else_label, end_label;
253 353
254 Visit(stmt->condition()); 354 VisitForAccumulatorValue(stmt->condition());
255 builder()->CastAccumulatorToBoolean(); 355 builder()->CastAccumulatorToBoolean();
256 builder()->JumpIfFalse(&else_label); 356 builder()->JumpIfFalse(&else_label);
257 Visit(stmt->then_statement()); 357 Visit(stmt->then_statement());
258 if (stmt->HasElseStatement()) { 358 if (stmt->HasElseStatement()) {
259 builder()->Jump(&end_label); 359 builder()->Jump(&end_label);
260 builder()->Bind(&else_label); 360 builder()->Bind(&else_label);
261 Visit(stmt->else_statement()); 361 Visit(stmt->else_statement());
262 } else { 362 } else {
263 builder()->Bind(&else_label); 363 builder()->Bind(&else_label);
264 } 364 }
(...skipping 11 matching lines...) Expand all
276 control_scope()->Continue(stmt->target()); 376 control_scope()->Continue(stmt->target());
277 } 377 }
278 378
279 379
280 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 380 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
281 control_scope()->Break(stmt->target()); 381 control_scope()->Break(stmt->target());
282 } 382 }
283 383
284 384
285 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 385 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
286 Visit(stmt->expression()); 386 VisitForAccumulatorValue(stmt->expression());
287 builder()->Return(); 387 builder()->Return();
288 } 388 }
289 389
290 390
291 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { 391 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
292 UNIMPLEMENTED(); 392 UNIMPLEMENTED();
293 } 393 }
294 394
295 395
296 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 396 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
297 UNIMPLEMENTED(); 397 UNIMPLEMENTED();
298 } 398 }
299 399
300 400
301 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } 401 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); }
302 402
303 403
304 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 404 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
305 LoopBuilder loop_builder(builder()); 405 LoopBuilder loop_builder(builder());
306 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 406 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
307 407
308 BytecodeLabel body_label, condition_label, done_label; 408 BytecodeLabel body_label, condition_label, done_label;
309 builder()->Bind(&body_label); 409 builder()->Bind(&body_label);
310 Visit(stmt->body()); 410 Visit(stmt->body());
311 builder()->Bind(&condition_label); 411 builder()->Bind(&condition_label);
312 Visit(stmt->cond()); 412 VisitForAccumulatorValue(stmt->cond());
313 builder()->JumpIfTrue(&body_label); 413 builder()->JumpIfTrue(&body_label);
314 builder()->Bind(&done_label); 414 builder()->Bind(&done_label);
315 415
316 loop_builder.SetBreakTarget(done_label); 416 loop_builder.SetBreakTarget(done_label);
317 loop_builder.SetContinueTarget(condition_label); 417 loop_builder.SetContinueTarget(condition_label);
318 } 418 }
319 419
320 420
321 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 421 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
322 LoopBuilder loop_builder(builder()); 422 LoopBuilder loop_builder(builder());
323 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 423 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
324 424
325 BytecodeLabel body_label, condition_label, done_label; 425 BytecodeLabel body_label, condition_label, done_label;
326 builder()->Jump(&condition_label); 426 builder()->Jump(&condition_label);
327 builder()->Bind(&body_label); 427 builder()->Bind(&body_label);
328 Visit(stmt->body()); 428 Visit(stmt->body());
329 builder()->Bind(&condition_label); 429 builder()->Bind(&condition_label);
330 Visit(stmt->cond()); 430 VisitForAccumulatorValue(stmt->cond());
331 builder()->JumpIfTrue(&body_label); 431 builder()->JumpIfTrue(&body_label);
332 builder()->Bind(&done_label); 432 builder()->Bind(&done_label);
333 433
334 loop_builder.SetBreakTarget(done_label); 434 loop_builder.SetBreakTarget(done_label);
335 loop_builder.SetContinueTarget(condition_label); 435 loop_builder.SetContinueTarget(condition_label);
336 } 436 }
337 437
338 438
339 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { 439 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
340 LoopBuilder loop_builder(builder()); 440 LoopBuilder loop_builder(builder());
341 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 441 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
342 442
343 if (stmt->init() != nullptr) { 443 if (stmt->init() != nullptr) {
344 Visit(stmt->init()); 444 Visit(stmt->init());
345 } 445 }
346 446
347 BytecodeLabel body_label, condition_label, next_label, done_label; 447 BytecodeLabel body_label, condition_label, next_label, done_label;
348 if (stmt->cond() != nullptr) { 448 if (stmt->cond() != nullptr) {
349 builder()->Jump(&condition_label); 449 builder()->Jump(&condition_label);
350 } 450 }
351 builder()->Bind(&body_label); 451 builder()->Bind(&body_label);
352 Visit(stmt->body()); 452 Visit(stmt->body());
353 builder()->Bind(&next_label); 453 builder()->Bind(&next_label);
354 if (stmt->next() != nullptr) { 454 if (stmt->next() != nullptr) {
355 Visit(stmt->next()); 455 Visit(stmt->next());
356 } 456 }
357 if (stmt->cond()) { 457 if (stmt->cond()) {
358 builder()->Bind(&condition_label); 458 builder()->Bind(&condition_label);
359 Visit(stmt->cond()); 459 VisitForAccumulatorValue(stmt->cond());
360 builder()->JumpIfTrue(&body_label); 460 builder()->JumpIfTrue(&body_label);
361 } else { 461 } else {
362 builder()->Jump(&body_label); 462 builder()->Jump(&body_label);
363 } 463 }
364 builder()->Bind(&done_label); 464 builder()->Bind(&done_label);
365 465
366 loop_builder.SetBreakTarget(done_label); 466 loop_builder.SetBreakTarget(done_label);
367 loop_builder.SetContinueTarget(next_label); 467 loop_builder.SetContinueTarget(next_label);
368 } 468 }
369 469
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 builder()->LoadTrue(); 522 builder()->LoadTrue();
423 } else if (value->IsFalse()) { 523 } else if (value->IsFalse()) {
424 builder()->LoadFalse(); 524 builder()->LoadFalse();
425 } else if (value->IsNull()) { 525 } else if (value->IsNull()) {
426 builder()->LoadNull(); 526 builder()->LoadNull();
427 } else if (value->IsTheHole()) { 527 } else if (value->IsTheHole()) {
428 builder()->LoadTheHole(); 528 builder()->LoadTheHole();
429 } else { 529 } else {
430 builder()->LoadLiteral(value); 530 builder()->LoadLiteral(value);
431 } 531 }
532 result_scope()->SetResultInAccumulator();
432 } 533 }
433 534
434 535
435 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 536 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
436 UNIMPLEMENTED(); 537 UNIMPLEMENTED();
437 } 538 }
438 539
439 540
440 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 541 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
441 UNIMPLEMENTED(); 542 UNIMPLEMENTED();
442 } 543 }
443 544
444 545
445 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 546 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
446 UNIMPLEMENTED(); 547 UNIMPLEMENTED();
447 } 548 }
448 549
449 550
450 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { 551 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
451 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 552 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
452 } 553 }
453 554
454 555
455 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 556 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
456 FeedbackVectorSlot slot) { 557 FeedbackVectorSlot slot) {
457 switch (variable->location()) { 558 switch (variable->location()) {
458 case VariableLocation::LOCAL: { 559 case VariableLocation::LOCAL: {
459 Register source(variable->index()); 560 result_scope()->SetResultInRegister(Register(variable->index()));
460 builder()->LoadAccumulatorWithRegister(source);
461 break; 561 break;
462 } 562 }
463 case VariableLocation::PARAMETER: { 563 case VariableLocation::PARAMETER: {
464 // The parameter indices are shifted by 1 (receiver is variable 564 // The parameter indices are shifted by 1 (receiver is variable
465 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 565 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
466 Register source(builder()->Parameter(variable->index() + 1)); 566 result_scope()->SetResultInRegister(
467 builder()->LoadAccumulatorWithRegister(source); 567 builder()->Parameter(variable->index() + 1));
468 break; 568 break;
469 } 569 }
470 case VariableLocation::GLOBAL: { 570 case VariableLocation::GLOBAL: {
471 // Global var, const, or let variable. 571 // Global var, const, or let variable.
472 // TODO(rmcilroy): If context chain depth is short enough, do this using 572 // TODO(rmcilroy): If context chain depth is short enough, do this using
473 // a generic version of LoadGlobalViaContextStub rather than calling the 573 // a generic version of LoadGlobalViaContextStub rather than calling the
474 // runtime. 574 // runtime.
475 DCHECK(variable->IsStaticGlobalObjectProperty()); 575 DCHECK(variable->IsStaticGlobalObjectProperty());
476 builder()->LoadGlobal(variable->index()); 576 builder()->LoadGlobal(variable->index());
577 result_scope()->SetResultInAccumulator();
477 break; 578 break;
478 } 579 }
479 case VariableLocation::UNALLOCATED: { 580 case VariableLocation::UNALLOCATED: {
480 TemporaryRegisterScope temporary_register_scope(&builder_); 581 TemporaryRegisterScope temporary_register_scope(&builder_);
481 Register obj = temporary_register_scope.NewRegister(); 582 Register obj = temporary_register_scope.NewRegister();
482 builder()->LoadContextSlot(current_context(), 583 builder()->LoadContextSlot(current_context(),
483 Context::GLOBAL_OBJECT_INDEX); 584 Context::GLOBAL_OBJECT_INDEX);
484 builder()->StoreAccumulatorInRegister(obj); 585 builder()->StoreAccumulatorInRegister(obj);
485 builder()->LoadLiteral(variable->name()); 586 builder()->LoadLiteral(variable->name());
486 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); 587 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode());
588 result_scope()->SetResultInAccumulator();
487 break; 589 break;
488 } 590 }
489 case VariableLocation::CONTEXT: 591 case VariableLocation::CONTEXT:
490 case VariableLocation::LOOKUP: 592 case VariableLocation::LOOKUP:
593 default:
rmcilroy 2015/10/09 13:02:56 Is this required? I'd prefer to avoid default: if
oth 2015/10/09 13:27:39 Acknowledged.
491 UNIMPLEMENTED(); 594 UNIMPLEMENTED();
492 } 595 }
493 } 596 }
494 597
495 598
496 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 599 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
497 FeedbackVectorSlot slot) { 600 FeedbackVectorSlot slot) {
498 switch (variable->location()) { 601 switch (variable->location()) {
499 case VariableLocation::LOCAL: { 602 case VariableLocation::LOCAL: {
500 // TODO(rmcilroy): support const mode initialization. 603 // TODO(rmcilroy): support const mode initialization.
(...skipping 30 matching lines...) Expand all
531 builder()->StoreAccumulatorInRegister(obj); 634 builder()->StoreAccumulatorInRegister(obj);
532 builder()->LoadLiteral(variable->name()); 635 builder()->LoadLiteral(variable->name());
533 builder()->StoreAccumulatorInRegister(name); 636 builder()->StoreAccumulatorInRegister(name);
534 builder()->LoadAccumulatorWithRegister(value); 637 builder()->LoadAccumulatorWithRegister(value);
535 builder()->StoreNamedProperty(obj, name, feedback_index(slot), 638 builder()->StoreNamedProperty(obj, name, feedback_index(slot),
536 language_mode()); 639 language_mode());
537 break; 640 break;
538 } 641 }
539 case VariableLocation::CONTEXT: 642 case VariableLocation::CONTEXT:
540 case VariableLocation::LOOKUP: 643 case VariableLocation::LOOKUP:
644 default:
541 UNIMPLEMENTED(); 645 UNIMPLEMENTED();
542 } 646 }
543 } 647 }
544 648
545 649
546 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 650 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
547 DCHECK(expr->target()->IsValidReferenceExpression()); 651 DCHECK(expr->target()->IsValidReferenceExpression());
548 TemporaryRegisterScope temporary_register_scope(&builder_); 652 TemporaryRegisterScope temporary_register_scope(builder());
549 Register object, key; 653 Register object, key;
550 654
551 // Left-hand side can only be a property, a global or a variable slot. 655 // Left-hand side can only be a property, a global or a variable slot.
552 Property* property = expr->target()->AsProperty(); 656 Property* property = expr->target()->AsProperty();
553 LhsKind assign_type = Property::GetAssignType(property); 657 LhsKind assign_type = Property::GetAssignType(property);
554 658
555 // Evaluate LHS expression. 659 // Evaluate LHS expression.
556 switch (assign_type) { 660 switch (assign_type) {
557 case VARIABLE: 661 case VARIABLE:
558 // Nothing to do to evaluate variable assignment LHS. 662 // Nothing to do to evaluate variable assignment LHS.
559 break; 663 break;
560 case NAMED_PROPERTY: 664 case NAMED_PROPERTY:
561 object = temporary_register_scope.NewRegister(); 665 object =
666 VisitForRegisterValue(property->obj(), &temporary_register_scope);
667 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName());
562 key = temporary_register_scope.NewRegister(); 668 key = temporary_register_scope.NewRegister();
563 Visit(property->obj());
564 builder()->StoreAccumulatorInRegister(object);
565 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName());
566 builder()->StoreAccumulatorInRegister(key); 669 builder()->StoreAccumulatorInRegister(key);
567 break; 670 break;
568 case KEYED_PROPERTY: 671 case KEYED_PROPERTY:
569 object = temporary_register_scope.NewRegister(); 672 object =
570 key = temporary_register_scope.NewRegister(); 673 VisitForRegisterValue(property->obj(), &temporary_register_scope);
571 Visit(property->obj()); 674 key = VisitForRegisterValue(property->key(), &temporary_register_scope);
572 builder()->StoreAccumulatorInRegister(object);
573 Visit(property->key());
574 builder()->StoreAccumulatorInRegister(key);
575 break; 675 break;
576 case NAMED_SUPER_PROPERTY: 676 case NAMED_SUPER_PROPERTY:
577 case KEYED_SUPER_PROPERTY: 677 case KEYED_SUPER_PROPERTY:
678 default:
578 UNIMPLEMENTED(); 679 UNIMPLEMENTED();
579 } 680 }
580 681
581 // Evaluate the value and potentially handle compound assignments by loading 682 // Evaluate the value and potentially handle compound assignments by loading
582 // the left-hand side value and performing a binary operation. 683 // the left-hand side value and performing a binary operation.
583 if (expr->is_compound()) { 684 if (expr->is_compound()) {
584 UNIMPLEMENTED(); 685 UNIMPLEMENTED();
585 } else { 686 } else {
586 Visit(expr->value()); 687 VisitForAccumulatorValue(expr->value());
688 result_scope()->SetResultInAccumulator();
587 } 689 }
588 690
589 // Store the value. 691 // Store the value.
590 FeedbackVectorSlot slot = expr->AssignmentSlot(); 692 FeedbackVectorSlot slot = expr->AssignmentSlot();
591 switch (assign_type) { 693 switch (assign_type) {
592 case VARIABLE: { 694 case VARIABLE: {
593 Variable* variable = expr->target()->AsVariableProxy()->var(); 695 Variable* variable = expr->target()->AsVariableProxy()->var();
594 VisitVariableAssignment(variable, slot); 696 VisitVariableAssignment(variable, slot);
595 break; 697 break;
596 } 698 }
(...skipping 20 matching lines...) Expand all
617 719
618 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { 720 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
619 LhsKind property_kind = Property::GetAssignType(expr); 721 LhsKind property_kind = Property::GetAssignType(expr);
620 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); 722 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
621 switch (property_kind) { 723 switch (property_kind) {
622 case VARIABLE: 724 case VARIABLE:
623 UNREACHABLE(); 725 UNREACHABLE();
624 case NAMED_PROPERTY: { 726 case NAMED_PROPERTY: {
625 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName()); 727 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName());
626 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); 728 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode());
729 result_scope()->SetResultInAccumulator();
627 break; 730 break;
628 } 731 }
629 case KEYED_PROPERTY: { 732 case KEYED_PROPERTY: {
630 Visit(expr->key()); 733 VisitForAccumulatorValue(expr->key());
631 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode()); 734 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode());
735 result_scope()->SetResultInAccumulator();
632 break; 736 break;
633 } 737 }
634 case NAMED_SUPER_PROPERTY: 738 case NAMED_SUPER_PROPERTY:
635 case KEYED_SUPER_PROPERTY: 739 case KEYED_SUPER_PROPERTY:
636 UNIMPLEMENTED(); 740 UNIMPLEMENTED();
637 } 741 }
638 } 742 }
639 743
640 744
641 void BytecodeGenerator::VisitProperty(Property* expr) { 745 void BytecodeGenerator::VisitProperty(Property* expr) {
642 TemporaryRegisterScope temporary_register_scope(&builder_); 746 TemporaryRegisterScope temporary_register_scope(builder());
643 Register obj = temporary_register_scope.NewRegister(); 747 Register obj = VisitForRegisterValue(expr->obj(), &temporary_register_scope);
644 Visit(expr->obj());
645 builder()->StoreAccumulatorInRegister(obj);
646 VisitPropertyLoad(obj, expr); 748 VisitPropertyLoad(obj, expr);
647 } 749 }
648 750
649 751
650 void BytecodeGenerator::VisitCall(Call* expr) { 752 void BytecodeGenerator::VisitCall(Call* expr) {
651 Expression* callee_expr = expr->expression(); 753 Expression* callee_expr = expr->expression();
652 Call::CallType call_type = expr->GetCallType(isolate()); 754 Call::CallType call_type = expr->GetCallType(isolate());
653 755
654 // Prepare the callee and the receiver to the function call. This depends on 756 // Prepare the callee and the receiver to the function call. This depends on
655 // the semantics of the underlying call type. 757 // the semantics of the underlying call type.
656 TemporaryRegisterScope temporary_register_scope(&builder_); 758 TemporaryRegisterScope temporary_register_scope(builder());
657 Register callee = temporary_register_scope.NewRegister(); 759 Register callee = temporary_register_scope.NewRegister();
760
761 // The receiver and arguments need to allocated consecutively for
762 // Call(). Future optimizations could avoid this there are no
763 // arguments or the receiver and arguments are already consecutive.
658 Register receiver = temporary_register_scope.NewRegister(); 764 Register receiver = temporary_register_scope.NewRegister();
659 765
660 switch (call_type) { 766 switch (call_type) {
661 case Call::PROPERTY_CALL: { 767 case Call::PROPERTY_CALL: {
662 Property* property = callee_expr->AsProperty(); 768 Property* property = callee_expr->AsProperty();
663 if (property->IsSuperAccess()) { 769 if (property->IsSuperAccess()) {
664 UNIMPLEMENTED(); 770 UNIMPLEMENTED();
665 } 771 }
666 Visit(property->obj()); 772 VisitForAccumulatorValue(property->obj());
667 builder()->StoreAccumulatorInRegister(receiver); 773 builder()->StoreAccumulatorInRegister(receiver);
668 // Perform a property load of the callee. 774 // Perform a property load of the callee.
669 VisitPropertyLoad(receiver, property); 775 VisitPropertyLoad(receiver, property);
670 builder()->StoreAccumulatorInRegister(callee); 776 builder()->StoreAccumulatorInRegister(callee);
671 break; 777 break;
672 } 778 }
673 case Call::GLOBAL_CALL: { 779 case Call::GLOBAL_CALL: {
674 // Receiver is undefined for global calls. 780 // Receiver is undefined for global calls.
675 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); 781 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
676 // Load callee as a global variable. 782 // Load callee as a global variable.
677 VariableProxy* proxy = callee_expr->AsVariableProxy(); 783 VariableProxy* proxy = callee_expr->AsVariableProxy();
678 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 784 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
679 builder()->StoreAccumulatorInRegister(callee); 785 builder()->StoreAccumulatorInRegister(callee);
680 break; 786 break;
681 } 787 }
682 case Call::LOOKUP_SLOT_CALL: 788 case Call::LOOKUP_SLOT_CALL:
683 case Call::SUPER_CALL: 789 case Call::SUPER_CALL:
684 case Call::POSSIBLY_EVAL_CALL: 790 case Call::POSSIBLY_EVAL_CALL:
685 case Call::OTHER_CALL: 791 case Call::OTHER_CALL:
686 UNIMPLEMENTED(); 792 UNIMPLEMENTED();
687 } 793 }
688 794
689 // Evaluate all arguments to the function call and store in sequential 795 // Evaluate all arguments to the function call and store in sequential
690 // registers. 796 // registers.
691 ZoneList<Expression*>* args = expr->arguments(); 797 ZoneList<Expression*>* args = expr->arguments();
692 for (int i = 0; i < args->length(); ++i) { 798 for (int i = 0; i < args->length(); ++i) {
693 Visit(args->at(i)); 799 VisitForAccumulatorValue(args->at(i));
694 Register arg = temporary_register_scope.NewRegister(); 800 Register arg = temporary_register_scope.NewRegister();
695 DCHECK(arg.index() - i == receiver.index() + 1); 801 DCHECK(arg.index() - i == receiver.index() + 1);
696 builder()->StoreAccumulatorInRegister(arg); 802 builder()->StoreAccumulatorInRegister(arg);
697 } 803 }
698 804
699 // TODO(rmcilroy): Deal with possible direct eval here? 805 // TODO(rmcilroy): Deal with possible direct eval here?
700 // TODO(rmcilroy): Use CallIC to allow call type feedback. 806 // TODO(rmcilroy): Use CallIC to allow call type feedback.
701 builder()->Call(callee, receiver, args->length()); 807 builder()->Call(callee, receiver, args->length());
808 result_scope()->SetResultInAccumulator();
702 } 809 }
703 810
704 811
705 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); } 812 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); }
706 813
707 814
708 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { 815 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
709 if (expr->is_jsruntime()) { 816 if (expr->is_jsruntime()) {
710 UNIMPLEMENTED(); 817 UNIMPLEMENTED();
711 } 818 }
712 819
713 // Evaluate all arguments to the runtime call. 820 // Evaluate all arguments to the runtime call.
714 ZoneList<Expression*>* args = expr->arguments(); 821 ZoneList<Expression*>* args = expr->arguments();
715 TemporaryRegisterScope temporary_register_scope(&builder_); 822 TemporaryRegisterScope temporary_register_scope(builder());
716 // Ensure we always have a valid first_arg register even if there are no 823 // Ensure we always have a valid first_arg register even if there are no
717 // arguments to pass. 824 // arguments to pass.
718 Register first_arg = temporary_register_scope.NewRegister(); 825 Register first_arg = temporary_register_scope.NewRegister();
719 for (int i = 0; i < args->length(); ++i) { 826 for (int i = 0; i < args->length(); ++i) {
720 Register arg = 827 Register arg =
721 (i == 0) ? first_arg : temporary_register_scope.NewRegister(); 828 (i == 0) ? first_arg : temporary_register_scope.NewRegister();
722 Visit(args->at(i)); 829 VisitForAccumulatorValue(args->at(i));
723 DCHECK_EQ(arg.index() - i, first_arg.index()); 830 DCHECK_EQ(arg.index() - i, first_arg.index());
724 builder()->StoreAccumulatorInRegister(arg); 831 builder()->StoreAccumulatorInRegister(arg);
725 } 832 }
726 833
727 // TODO(rmcilroy): support multiple return values. 834 // TODO(rmcilroy): support multiple return values.
728 DCHECK_LE(expr->function()->result_size, 1); 835 DCHECK_LE(expr->function()->result_size, 1);
729 Runtime::FunctionId function_id = expr->function()->function_id; 836 Runtime::FunctionId function_id = expr->function()->function_id;
730 builder()->CallRuntime(function_id, first_arg, args->length()); 837 builder()->CallRuntime(function_id, first_arg, args->length());
838 result_scope()->SetResultInAccumulator();
731 } 839 }
732 840
733 841
734 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { 842 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
735 Visit(expr->expression()); 843 VisitForEffect(expr->expression());
736 builder()->LoadUndefined(); 844 builder()->LoadUndefined();
845 result_scope()->SetResultInAccumulator();
737 } 846 }
738 847
739 848
740 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { 849 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
741 Visit(expr->expression()); 850 VisitForAccumulatorValue(expr->expression());
742 builder()->TypeOf(); 851 builder()->TypeOf();
852 result_scope()->SetResultInAccumulator();
743 } 853 }
744 854
745 855
746 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { 856 void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
747 Visit(expr->expression()); 857 VisitForAccumulatorValue(expr->expression());
748 builder()->LogicalNot(); 858 builder()->LogicalNot();
859 result_scope()->SetResultInAccumulator();
749 } 860 }
750 861
751 862
752 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 863 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
753 switch (expr->op()) { 864 switch (expr->op()) {
754 case Token::Value::NOT: 865 case Token::Value::NOT:
755 VisitNot(expr); 866 VisitNot(expr);
756 break; 867 break;
757 case Token::Value::TYPEOF: 868 case Token::Value::TYPEOF:
758 VisitTypeOf(expr); 869 VisitTypeOf(expr);
(...skipping 23 matching lines...) Expand all
782 UNIMPLEMENTED(); 893 UNIMPLEMENTED();
783 break; 894 break;
784 default: 895 default:
785 VisitArithmeticExpression(binop); 896 VisitArithmeticExpression(binop);
786 break; 897 break;
787 } 898 }
788 } 899 }
789 900
790 901
791 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { 902 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
792 Token::Value op = expr->op(); 903 TemporaryRegisterScope temporary_register_scope(builder());
793 Expression* left = expr->left(); 904 Register lhs = VisitForRegisterValue(expr->left(), &temporary_register_scope);
794 Expression* right = expr->right(); 905 VisitForAccumulatorValue(expr->right());
795 906 builder()->CompareOperation(expr->op(), lhs, language_mode_strength());
796 TemporaryRegisterScope temporary_register_scope(&builder_); 907 result_scope()->SetResultInAccumulator();
797 Register temporary = temporary_register_scope.NewRegister();
798
799 Visit(left);
800 builder()->StoreAccumulatorInRegister(temporary);
801 Visit(right);
802 builder()->CompareOperation(op, temporary, language_mode_strength());
803 } 908 }
804 909
805 910
806 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } 911 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
807 912
808 913
809 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { 914 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
810 UNREACHABLE(); 915 UNREACHABLE();
811 } 916 }
812 917
813 918
814 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { 919 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
815 UNIMPLEMENTED(); 920 UNIMPLEMENTED();
816 } 921 }
817 922
818 923
819 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { 924 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
820 UNIMPLEMENTED(); 925 UNIMPLEMENTED();
821 } 926 }
822 927
823 928
824 void BytecodeGenerator::VisitSuperPropertyReference( 929 void BytecodeGenerator::VisitSuperPropertyReference(
825 SuperPropertyReference* expr) { 930 SuperPropertyReference* expr) {
826 UNIMPLEMENTED(); 931 UNIMPLEMENTED();
827 } 932 }
828 933
829 934
830 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { 935 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) {
831 Token::Value op = binop->op(); 936 TemporaryRegisterScope temporary_register_scope(builder());
832 Expression* left = binop->left(); 937 Register lhs =
833 Expression* right = binop->right(); 938 VisitForRegisterValue(binop->left(), &temporary_register_scope);
834 939 VisitForAccumulatorValue(binop->right());
835 TemporaryRegisterScope temporary_register_scope(&builder_); 940 builder()->BinaryOperation(binop->op(), lhs, language_mode_strength());
836 Register temporary = temporary_register_scope.NewRegister(); 941 result_scope()->SetResultInAccumulator();
837
838 Visit(left);
839 builder()->StoreAccumulatorInRegister(temporary);
840 Visit(right);
841 builder()->BinaryOperation(op, temporary, language_mode_strength());
842 } 942 }
843 943
844 944
945 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
946 AccumulatorResultScope accumulator_scope(this);
947 Visit(expr);
948 }
949
950
951 void BytecodeGenerator::VisitForEffect(Expression* node) {
952 EffectResultScope effect_scope(this);
953 Visit(node);
954 }
955
956 Register BytecodeGenerator::VisitForRegisterValue(
957 Expression* expr, TemporaryRegisterScope* temporary_register_scope) {
958 RegisterResultScope register_scope(this, temporary_register_scope);
959 Visit(expr);
960 return GetResultRegister();
961 }
962
963
964 void BytecodeGenerator::SetResultRegister(Register reg) {
965 DCHECK(result_register_.IsNothing());
966 result_register_ = Just<Register>(reg);
967 }
968
969
970 Register BytecodeGenerator::GetResultRegister() {
971 Register reg = result_register_.FromJust();
972 result_register_ = Nothing<Register>();
973 return reg;
974 }
975
976
977 bool BytecodeGenerator::ResultRegisterIsEmpty() const {
978 return result_register_.IsNothing();
979 }
980
845 LanguageMode BytecodeGenerator::language_mode() const { 981 LanguageMode BytecodeGenerator::language_mode() const {
846 return info()->language_mode(); 982 return info()->language_mode();
847 } 983 }
848 984
849 985
850 Strength BytecodeGenerator::language_mode_strength() const { 986 Strength BytecodeGenerator::language_mode_strength() const {
851 return strength(language_mode()); 987 return strength(language_mode());
852 } 988 }
853 989
854 990
855 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 991 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
856 return info()->feedback_vector()->GetIndex(slot); 992 return info()->feedback_vector()->GetIndex(slot);
857 } 993 }
858 994
859 995
860 Register BytecodeGenerator::current_context() const { return current_context_; } 996 Register BytecodeGenerator::current_context() const { return current_context_; }
861 997
862 } // namespace interpreter 998 } // namespace interpreter
863 } // namespace internal 999 } // namespace internal
864 } // namespace v8 1000 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | test/cctest/interpreter/test-bytecode-generator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698