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

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: Rebase. 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), outer_(generator->result_scope()) {
98 generator_->set_result_scope(this);
99 }
100
101 virtual ~ExpressionResultScope() { generator_->set_result_scope(outer_); }
102
103 virtual void AccumulatorSet() = 0;
104 virtual void RegisterSet(Register reg) = 0;
rmcilroy 2015/10/08 16:54:26 Not sure I like these names. How about SetResultIn
oth 2015/10/09 12:50:48 Done.
105
106 BytecodeGenerator* generator() const { return generator_; }
107 BytecodeArrayBuilder* builder() const { return generator()->builder(); }
108
109 private:
110 BytecodeGenerator* generator_;
111 ExpressionResultScope* outer_;
112 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
113 };
114
115
116 // Scoped class used when the result of the current expression to be
117 // evaluated should go into the interpreter's accumulator register.
118 class BytecodeGenerator::AccumulatorResultScope final
119 : public ExpressionResultScope {
120 public:
121 explicit AccumulatorResultScope(BytecodeGenerator* generator)
122 : ExpressionResultScope(generator) {}
123 virtual void AccumulatorSet() {}
124 virtual void RegisterSet(Register reg) {
125 builder()->LoadAccumulatorWithRegister(reg);
rmcilroy 2015/10/08 16:54:26 As discussed offline, could we add a DCHECK to mak
oth 2015/10/09 12:50:48 Done.
126 }
127 };
128
129
130 // Scoped class used when the result of the current expression to be
131 // evaluated should go into an interpreter register. The register
132 // selected is then available when GetResultRegister() is called.
133 class BytecodeGenerator::RegisterResultScope final
134 : public ExpressionResultScope {
135 public:
136 explicit RegisterResultScope(BytecodeGenerator* generator,
137 TemporaryRegisterScope* register_scope)
138 : ExpressionResultScope(generator), register_scope_(register_scope) {}
139
140 virtual void AccumulatorSet() {
141 Register allocated = register_scope_->NewRegister();
142 builder()->StoreAccumulatorInRegister(allocated);
143 generator()->SetResultRegister(allocated);
144 }
145
146 virtual void RegisterSet(Register reg) {
147 generator()->SetResultRegister(reg);
148 }
149
150 private:
151 TemporaryRegisterScope* register_scope_;
152 };
153
rmcilroy 2015/10/08 16:54:26 As discussed offline, could we also add a NullResu
oth 2015/10/09 12:50:48 If the ast visitor is not in an expression then th
154
92 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) 155 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
93 : builder_(isolate, zone), 156 : builder_(isolate, zone),
94 info_(nullptr), 157 info_(nullptr),
95 scope_(nullptr), 158 scope_(nullptr),
96 globals_(0, zone), 159 globals_(0, zone),
97 control_scope_(nullptr), 160 control_scope_(nullptr),
98 current_context_(Register::function_context()) { 161 current_context_(Register::function_context()),
162 result_scope_(nullptr),
163 result_register_(Nothing<Register>()) {
99 InitializeAstVisitor(isolate, zone); 164 InitializeAstVisitor(isolate, zone);
100 } 165 }
101 166
102 167
103 BytecodeGenerator::~BytecodeGenerator() {} 168 BytecodeGenerator::~BytecodeGenerator() {}
104 169
105 170
106 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { 171 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
107 set_info(info); 172 set_info(info);
108 set_scope(info->scope()); 173 set_scope(info->scope());
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); 293 builder()->LoadLiteral(Smi::FromInt(encoded_flags));
229 builder()->StoreAccumulatorInRegister(flags); 294 builder()->StoreAccumulatorInRegister(flags);
230 DCHECK(flags.index() == pairs.index() + 1); 295 DCHECK(flags.index() == pairs.index() + 1);
231 296
232 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); 297 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2);
233 globals()->clear(); 298 globals()->clear();
234 } 299 }
235 300
236 301
237 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 302 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
238 Visit(stmt->expression()); 303 VisitForAccumulatorValue(stmt->expression());
239 } 304 }
240 305
241 306
242 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 307 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
243 // TODO(oth): For control-flow it could be useful to signal empty paths here. 308 // TODO(oth): For control-flow it could be useful to signal empty paths here.
244 } 309 }
245 310
246 311
247 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { 312 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
248 // TODO(oth): Spot easy cases where there code would not need to 313 // 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 314 // emit the then block or the else block, e.g. condition is
250 // obviously true/1/false/0. 315 // obviously true/1/false/0.
251 316
252 BytecodeLabel else_label, end_label; 317 BytecodeLabel else_label, end_label;
253 318
254 Visit(stmt->condition()); 319 VisitForAccumulatorValue(stmt->condition());
255 builder()->CastAccumulatorToBoolean(); 320 builder()->CastAccumulatorToBoolean();
256 builder()->JumpIfFalse(&else_label); 321 builder()->JumpIfFalse(&else_label);
257 Visit(stmt->then_statement()); 322 Visit(stmt->then_statement());
258 if (stmt->HasElseStatement()) { 323 if (stmt->HasElseStatement()) {
259 builder()->Jump(&end_label); 324 builder()->Jump(&end_label);
260 builder()->Bind(&else_label); 325 builder()->Bind(&else_label);
261 Visit(stmt->else_statement()); 326 Visit(stmt->else_statement());
262 } else { 327 } else {
263 builder()->Bind(&else_label); 328 builder()->Bind(&else_label);
264 } 329 }
(...skipping 11 matching lines...) Expand all
276 control_scope()->Continue(stmt->target()); 341 control_scope()->Continue(stmt->target());
277 } 342 }
278 343
279 344
280 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 345 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
281 control_scope()->Break(stmt->target()); 346 control_scope()->Break(stmt->target());
282 } 347 }
283 348
284 349
285 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 350 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
286 Visit(stmt->expression()); 351 VisitForAccumulatorValue(stmt->expression());
287 builder()->Return(); 352 builder()->Return();
288 } 353 }
289 354
290 355
291 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { 356 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
292 UNIMPLEMENTED(); 357 UNIMPLEMENTED();
293 } 358 }
294 359
295 360
296 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 361 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
297 UNIMPLEMENTED(); 362 UNIMPLEMENTED();
298 } 363 }
299 364
300 365
301 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } 366 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); }
302 367
303 368
304 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 369 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
305 LoopBuilder loop_builder(builder()); 370 LoopBuilder loop_builder(builder());
306 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 371 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
307 372
308 BytecodeLabel body_label, condition_label, done_label; 373 BytecodeLabel body_label, condition_label, done_label;
309 builder()->Bind(&body_label); 374 builder()->Bind(&body_label);
310 Visit(stmt->body()); 375 Visit(stmt->body());
311 builder()->Bind(&condition_label); 376 builder()->Bind(&condition_label);
312 Visit(stmt->cond()); 377 VisitForAccumulatorValue(stmt->cond());
313 builder()->JumpIfTrue(&body_label); 378 builder()->JumpIfTrue(&body_label);
314 builder()->Bind(&done_label); 379 builder()->Bind(&done_label);
315 380
316 loop_builder.SetBreakTarget(done_label); 381 loop_builder.SetBreakTarget(done_label);
317 loop_builder.SetContinueTarget(condition_label); 382 loop_builder.SetContinueTarget(condition_label);
318 } 383 }
319 384
320 385
321 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 386 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
322 LoopBuilder loop_builder(builder()); 387 LoopBuilder loop_builder(builder());
323 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 388 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
324 389
325 BytecodeLabel body_label, condition_label, done_label; 390 BytecodeLabel body_label, condition_label, done_label;
326 builder()->Jump(&condition_label); 391 builder()->Jump(&condition_label);
327 builder()->Bind(&body_label); 392 builder()->Bind(&body_label);
328 Visit(stmt->body()); 393 Visit(stmt->body());
329 builder()->Bind(&condition_label); 394 builder()->Bind(&condition_label);
330 Visit(stmt->cond()); 395 VisitForAccumulatorValue(stmt->cond());
331 builder()->JumpIfTrue(&body_label); 396 builder()->JumpIfTrue(&body_label);
332 builder()->Bind(&done_label); 397 builder()->Bind(&done_label);
333 398
334 loop_builder.SetBreakTarget(done_label); 399 loop_builder.SetBreakTarget(done_label);
335 loop_builder.SetContinueTarget(condition_label); 400 loop_builder.SetContinueTarget(condition_label);
336 } 401 }
337 402
338 403
339 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { 404 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
340 LoopBuilder loop_builder(builder()); 405 LoopBuilder loop_builder(builder());
341 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 406 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
342 407
343 if (stmt->init() != nullptr) { 408 if (stmt->init() != nullptr) {
344 Visit(stmt->init()); 409 Visit(stmt->init());
345 } 410 }
346 411
347 BytecodeLabel body_label, condition_label, next_label, done_label; 412 BytecodeLabel body_label, condition_label, next_label, done_label;
348 if (stmt->cond() != nullptr) { 413 if (stmt->cond() != nullptr) {
349 builder()->Jump(&condition_label); 414 builder()->Jump(&condition_label);
350 } 415 }
351 builder()->Bind(&body_label); 416 builder()->Bind(&body_label);
352 Visit(stmt->body()); 417 Visit(stmt->body());
353 builder()->Bind(&next_label); 418 builder()->Bind(&next_label);
354 if (stmt->next() != nullptr) { 419 if (stmt->next() != nullptr) {
355 Visit(stmt->next()); 420 Visit(stmt->next());
356 } 421 }
357 if (stmt->cond()) { 422 if (stmt->cond()) {
358 builder()->Bind(&condition_label); 423 builder()->Bind(&condition_label);
359 Visit(stmt->cond()); 424 VisitForAccumulatorValue(stmt->cond());
360 builder()->JumpIfTrue(&body_label); 425 builder()->JumpIfTrue(&body_label);
361 } else { 426 } else {
362 builder()->Jump(&body_label); 427 builder()->Jump(&body_label);
363 } 428 }
364 builder()->Bind(&done_label); 429 builder()->Bind(&done_label);
365 430
366 loop_builder.SetBreakTarget(done_label); 431 loop_builder.SetBreakTarget(done_label);
367 loop_builder.SetContinueTarget(next_label); 432 loop_builder.SetContinueTarget(next_label);
368 } 433 }
369 434
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
422 builder()->LoadTrue(); 487 builder()->LoadTrue();
423 } else if (value->IsFalse()) { 488 } else if (value->IsFalse()) {
424 builder()->LoadFalse(); 489 builder()->LoadFalse();
425 } else if (value->IsNull()) { 490 } else if (value->IsNull()) {
426 builder()->LoadNull(); 491 builder()->LoadNull();
427 } else if (value->IsTheHole()) { 492 } else if (value->IsTheHole()) {
428 builder()->LoadTheHole(); 493 builder()->LoadTheHole();
429 } else { 494 } else {
430 builder()->LoadLiteral(value); 495 builder()->LoadLiteral(value);
431 } 496 }
497 result_scope()->AccumulatorSet();
432 } 498 }
433 499
434 500
435 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { 501 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
436 UNIMPLEMENTED(); 502 UNIMPLEMENTED();
437 } 503 }
438 504
439 505
440 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { 506 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
441 UNIMPLEMENTED(); 507 UNIMPLEMENTED();
442 } 508 }
443 509
444 510
445 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 511 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
446 UNIMPLEMENTED(); 512 UNIMPLEMENTED();
447 } 513 }
448 514
449 515
450 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { 516 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
451 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 517 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
452 } 518 }
453 519
454 520
455 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 521 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
456 FeedbackVectorSlot slot) { 522 FeedbackVectorSlot slot) {
457 switch (variable->location()) { 523 switch (variable->location()) {
458 case VariableLocation::LOCAL: { 524 case VariableLocation::LOCAL: {
459 Register source(variable->index()); 525 result_scope()->RegisterSet(Register(variable->index()));
460 builder()->LoadAccumulatorWithRegister(source);
461 break; 526 break;
462 } 527 }
463 case VariableLocation::PARAMETER: { 528 case VariableLocation::PARAMETER: {
464 // The parameter indices are shifted by 1 (receiver is variable 529 // The parameter indices are shifted by 1 (receiver is variable
465 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 530 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
466 Register source(builder()->Parameter(variable->index() + 1)); 531 result_scope()->RegisterSet(builder()->Parameter(variable->index() + 1));
467 builder()->LoadAccumulatorWithRegister(source);
468 break; 532 break;
469 } 533 }
470 case VariableLocation::GLOBAL: { 534 case VariableLocation::GLOBAL: {
471 // Global var, const, or let variable. 535 // Global var, const, or let variable.
472 // TODO(rmcilroy): If context chain depth is short enough, do this using 536 // TODO(rmcilroy): If context chain depth is short enough, do this using
473 // a generic version of LoadGlobalViaContextStub rather than calling the 537 // a generic version of LoadGlobalViaContextStub rather than calling the
474 // runtime. 538 // runtime.
475 DCHECK(variable->IsStaticGlobalObjectProperty()); 539 DCHECK(variable->IsStaticGlobalObjectProperty());
476 builder()->LoadGlobal(variable->index()); 540 builder()->LoadGlobal(variable->index());
541 result_scope()->AccumulatorSet();
477 break; 542 break;
478 } 543 }
479 case VariableLocation::UNALLOCATED: { 544 case VariableLocation::UNALLOCATED: {
480 TemporaryRegisterScope temporary_register_scope(&builder_); 545 TemporaryRegisterScope temporary_register_scope(&builder_);
481 Register obj = temporary_register_scope.NewRegister(); 546 Register obj = temporary_register_scope.NewRegister();
482 builder()->LoadContextSlot(current_context(), 547 builder()->LoadContextSlot(current_context(),
483 Context::GLOBAL_OBJECT_INDEX); 548 Context::GLOBAL_OBJECT_INDEX);
484 builder()->StoreAccumulatorInRegister(obj); 549 builder()->StoreAccumulatorInRegister(obj);
485 builder()->LoadLiteral(variable->name()); 550 builder()->LoadLiteral(variable->name());
486 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); 551 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode());
rmcilroy 2015/10/08 16:54:26 AccumulatorSet()
oth 2015/10/09 12:50:48 Done.
487 break; 552 break;
488 } 553 }
489 case VariableLocation::CONTEXT: 554 case VariableLocation::CONTEXT:
490 case VariableLocation::LOOKUP: 555 case VariableLocation::LOOKUP:
491 UNIMPLEMENTED(); 556 UNIMPLEMENTED();
492 } 557 }
493 } 558 }
494 559
495 560
496 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 561 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
497 FeedbackVectorSlot slot) { 562 FeedbackVectorSlot slot) {
498 switch (variable->location()) { 563 switch (variable->location()) {
499 case VariableLocation::LOCAL: { 564 case VariableLocation::LOCAL: {
500 // TODO(rmcilroy): support const mode initialization. 565 // TODO(rmcilroy): support const mode initialization.
501 Register destination(variable->index()); 566 Register destination(variable->index());
502 builder()->StoreAccumulatorInRegister(destination); 567 builder()->StoreAccumulatorInRegister(destination);
rmcilroy 2015/10/08 16:54:25 I was chatting to Danno about this and he made a v
rmcilroy 2015/10/08 17:00:09 Had a further chat with Danno about this, if we ke
oth 2015/10/09 12:50:48 Yes, a bit of a fail not to have recalled this was
503 break; 568 break;
504 } 569 }
505 case VariableLocation::PARAMETER: { 570 case VariableLocation::PARAMETER: {
506 // The parameter indices are shifted by 1 (receiver is variable 571 // The parameter indices are shifted by 1 (receiver is variable
507 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 572 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
508 Register destination(builder()->Parameter(variable->index() + 1)); 573 Register destination(builder()->Parameter(variable->index() + 1));
509 builder()->StoreAccumulatorInRegister(destination); 574 builder()->StoreAccumulatorInRegister(destination);
510 break; 575 break;
511 } 576 }
512 case VariableLocation::GLOBAL: { 577 case VariableLocation::GLOBAL: {
(...skipping 25 matching lines...) Expand all
538 } 603 }
539 case VariableLocation::CONTEXT: 604 case VariableLocation::CONTEXT:
540 case VariableLocation::LOOKUP: 605 case VariableLocation::LOOKUP:
541 UNIMPLEMENTED(); 606 UNIMPLEMENTED();
542 } 607 }
543 } 608 }
544 609
545 610
546 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 611 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
547 DCHECK(expr->target()->IsValidReferenceExpression()); 612 DCHECK(expr->target()->IsValidReferenceExpression());
548 TemporaryRegisterScope temporary_register_scope(&builder_); 613 TemporaryRegisterScope temporary_register_scope(builder());
549 Register object, key; 614 Register object, key;
550 615
551 // Left-hand side can only be a property, a global or a variable slot. 616 // Left-hand side can only be a property, a global or a variable slot.
552 Property* property = expr->target()->AsProperty(); 617 Property* property = expr->target()->AsProperty();
553 LhsKind assign_type = Property::GetAssignType(property); 618 LhsKind assign_type = Property::GetAssignType(property);
554 619
555 // Evaluate LHS expression. 620 // Evaluate LHS expression.
556 switch (assign_type) { 621 switch (assign_type) {
557 case VARIABLE: 622 case VARIABLE:
558 // Nothing to do to evaluate variable assignment LHS. 623 // Nothing to do to evaluate variable assignment LHS.
559 break; 624 break;
560 case NAMED_PROPERTY: 625 case NAMED_PROPERTY:
561 object = temporary_register_scope.NewRegister(); 626 VisitForRegisterValue(property->obj(), &temporary_register_scope);
627 object = GetResultRegister();
628 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName());
562 key = temporary_register_scope.NewRegister(); 629 key = temporary_register_scope.NewRegister();
563 Visit(property->obj());
564 builder()->StoreAccumulatorInRegister(object);
565 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName());
566 builder()->StoreAccumulatorInRegister(key); 630 builder()->StoreAccumulatorInRegister(key);
567 break; 631 break;
568 case KEYED_PROPERTY: 632 case KEYED_PROPERTY:
569 object = temporary_register_scope.NewRegister(); 633 VisitForRegisterValue(property->obj(), &temporary_register_scope);
570 key = temporary_register_scope.NewRegister(); 634 object = GetResultRegister();
571 Visit(property->obj()); 635 VisitForRegisterValue(property->key(), &temporary_register_scope);
572 builder()->StoreAccumulatorInRegister(object); 636 key = GetResultRegister();
573 Visit(property->key());
574 builder()->StoreAccumulatorInRegister(key);
575 break; 637 break;
576 case NAMED_SUPER_PROPERTY: 638 case NAMED_SUPER_PROPERTY:
577 case KEYED_SUPER_PROPERTY: 639 case KEYED_SUPER_PROPERTY:
578 UNIMPLEMENTED(); 640 UNIMPLEMENTED();
579 } 641 }
580 642
581 // Evaluate the value and potentially handle compound assignments by loading 643 // Evaluate the value and potentially handle compound assignments by loading
582 // the left-hand side value and performing a binary operation. 644 // the left-hand side value and performing a binary operation.
583 if (expr->is_compound()) { 645 if (expr->is_compound()) {
584 UNIMPLEMENTED(); 646 UNIMPLEMENTED();
585 } else { 647 } else {
586 Visit(expr->value()); 648 VisitForAccumulatorValue(expr->value());
587 } 649 }
588 650
589 // Store the value. 651 // Store the value.
590 FeedbackVectorSlot slot = expr->AssignmentSlot(); 652 FeedbackVectorSlot slot = expr->AssignmentSlot();
591 switch (assign_type) { 653 switch (assign_type) {
592 case VARIABLE: { 654 case VARIABLE: {
593 Variable* variable = expr->target()->AsVariableProxy()->var(); 655 Variable* variable = expr->target()->AsVariableProxy()->var();
594 VisitVariableAssignment(variable, slot); 656 VisitVariableAssignment(variable, slot);
595 break; 657 break;
596 } 658 }
(...skipping 23 matching lines...) Expand all
620 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); 682 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
621 switch (property_kind) { 683 switch (property_kind) {
622 case VARIABLE: 684 case VARIABLE:
623 UNREACHABLE(); 685 UNREACHABLE();
624 case NAMED_PROPERTY: { 686 case NAMED_PROPERTY: {
625 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName()); 687 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName());
626 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); 688 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode());
627 break; 689 break;
628 } 690 }
629 case KEYED_PROPERTY: { 691 case KEYED_PROPERTY: {
630 Visit(expr->key()); 692 VisitForAccumulatorValue(expr->key());
631 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode()); 693 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode());
632 break; 694 break;
633 } 695 }
634 case NAMED_SUPER_PROPERTY: 696 case NAMED_SUPER_PROPERTY:
635 case KEYED_SUPER_PROPERTY: 697 case KEYED_SUPER_PROPERTY:
636 UNIMPLEMENTED(); 698 UNIMPLEMENTED();
637 } 699 }
638 } 700 }
639 701
640 702
641 void BytecodeGenerator::VisitProperty(Property* expr) { 703 void BytecodeGenerator::VisitProperty(Property* expr) {
642 TemporaryRegisterScope temporary_register_scope(&builder_); 704 TemporaryRegisterScope temporary_register_scope(builder());
643 Register obj = temporary_register_scope.NewRegister(); 705 VisitForRegisterValue(expr->obj(), &temporary_register_scope);
644 Visit(expr->obj()); 706 VisitPropertyLoad(GetResultRegister(), expr);
645 builder()->StoreAccumulatorInRegister(obj);
646 VisitPropertyLoad(obj, expr);
647 } 707 }
648 708
649 709
650 void BytecodeGenerator::VisitCall(Call* expr) { 710 void BytecodeGenerator::VisitCall(Call* expr) {
651 Expression* callee_expr = expr->expression(); 711 Expression* callee_expr = expr->expression();
652 Call::CallType call_type = expr->GetCallType(isolate()); 712 Call::CallType call_type = expr->GetCallType(isolate());
653 713
654 // Prepare the callee and the receiver to the function call. This depends on 714 // Prepare the callee and the receiver to the function call. This depends on
655 // the semantics of the underlying call type. 715 // the semantics of the underlying call type.
656 TemporaryRegisterScope temporary_register_scope(&builder_); 716 TemporaryRegisterScope temporary_register_scope(builder());
657 Register callee = temporary_register_scope.NewRegister(); 717 Register callee = temporary_register_scope.NewRegister();
658 Register receiver = temporary_register_scope.NewRegister(); 718 Register receiver = temporary_register_scope.NewRegister();
659 719
660 switch (call_type) { 720 switch (call_type) {
661 case Call::PROPERTY_CALL: { 721 case Call::PROPERTY_CALL: {
662 Property* property = callee_expr->AsProperty(); 722 Property* property = callee_expr->AsProperty();
663 if (property->IsSuperAccess()) { 723 if (property->IsSuperAccess()) {
664 UNIMPLEMENTED(); 724 UNIMPLEMENTED();
665 } 725 }
666 Visit(property->obj()); 726 VisitForAccumulatorValue(property->obj());
727 // Receiver needs to explicitly be in a register, cannot be
728 // a param. Hence explicit allocation and store.
rmcilroy 2015/10/08 16:54:25 If there were no other arguments (or all the argum
oth 2015/10/09 12:50:48 Done.
667 builder()->StoreAccumulatorInRegister(receiver); 729 builder()->StoreAccumulatorInRegister(receiver);
668 // Perform a property load of the callee. 730 // Perform a property load of the callee.
669 VisitPropertyLoad(receiver, property); 731 VisitPropertyLoad(receiver, property);
670 builder()->StoreAccumulatorInRegister(callee); 732 builder()->StoreAccumulatorInRegister(callee);
671 break; 733 break;
672 } 734 }
673 case Call::GLOBAL_CALL: { 735 case Call::GLOBAL_CALL: {
674 // Receiver is undefined for global calls. 736 // Receiver is undefined for global calls.
675 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); 737 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
676 // Load callee as a global variable. 738 // Load callee as a global variable.
677 VariableProxy* proxy = callee_expr->AsVariableProxy(); 739 VariableProxy* proxy = callee_expr->AsVariableProxy();
678 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 740 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
679 builder()->StoreAccumulatorInRegister(callee); 741 builder()->StoreAccumulatorInRegister(callee);
680 break; 742 break;
681 } 743 }
682 case Call::LOOKUP_SLOT_CALL: 744 case Call::LOOKUP_SLOT_CALL:
683 case Call::SUPER_CALL: 745 case Call::SUPER_CALL:
684 case Call::POSSIBLY_EVAL_CALL: 746 case Call::POSSIBLY_EVAL_CALL:
685 case Call::OTHER_CALL: 747 case Call::OTHER_CALL:
686 UNIMPLEMENTED(); 748 UNIMPLEMENTED();
687 } 749 }
688 750
689 // Evaluate all arguments to the function call and store in sequential 751 // Evaluate all arguments to the function call and store in sequential
690 // registers. 752 // registers.
691 ZoneList<Expression*>* args = expr->arguments(); 753 ZoneList<Expression*>* args = expr->arguments();
692 for (int i = 0; i < args->length(); ++i) { 754 for (int i = 0; i < args->length(); ++i) {
693 Visit(args->at(i)); 755 VisitForAccumulatorValue(args->at(i));
694 Register arg = temporary_register_scope.NewRegister(); 756 Register arg = temporary_register_scope.NewRegister();
695 DCHECK(arg.index() - i == receiver.index() + 1); 757 DCHECK(arg.index() - i == receiver.index() + 1);
696 builder()->StoreAccumulatorInRegister(arg); 758 builder()->StoreAccumulatorInRegister(arg);
697 } 759 }
698 760
699 // TODO(rmcilroy): Deal with possible direct eval here? 761 // TODO(rmcilroy): Deal with possible direct eval here?
700 // TODO(rmcilroy): Use CallIC to allow call type feedback. 762 // TODO(rmcilroy): Use CallIC to allow call type feedback.
701 builder()->Call(callee, receiver, args->length()); 763 builder()->Call(callee, receiver, args->length());
702 } 764 }
703 765
704 766
705 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); } 767 void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); }
706 768
707 769
708 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { 770 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
709 if (expr->is_jsruntime()) { 771 if (expr->is_jsruntime()) {
710 UNIMPLEMENTED(); 772 UNIMPLEMENTED();
711 } 773 }
712 774
713 // Evaluate all arguments to the runtime call. 775 // Evaluate all arguments to the runtime call.
714 ZoneList<Expression*>* args = expr->arguments(); 776 ZoneList<Expression*>* args = expr->arguments();
715 TemporaryRegisterScope temporary_register_scope(&builder_); 777 TemporaryRegisterScope temporary_register_scope(builder());
716 // Ensure we always have a valid first_arg register even if there are no 778 // Ensure we always have a valid first_arg register even if there are no
717 // arguments to pass. 779 // arguments to pass.
718 Register first_arg = temporary_register_scope.NewRegister(); 780 Register first_arg = temporary_register_scope.NewRegister();
719 for (int i = 0; i < args->length(); ++i) { 781 for (int i = 0; i < args->length(); ++i) {
720 Register arg = 782 Register arg =
721 (i == 0) ? first_arg : temporary_register_scope.NewRegister(); 783 (i == 0) ? first_arg : temporary_register_scope.NewRegister();
722 Visit(args->at(i)); 784 VisitForAccumulatorValue(args->at(i));
723 DCHECK_EQ(arg.index() - i, first_arg.index()); 785 DCHECK_EQ(arg.index() - i, first_arg.index());
724 builder()->StoreAccumulatorInRegister(arg); 786 builder()->StoreAccumulatorInRegister(arg);
725 } 787 }
726 788
727 // TODO(rmcilroy): support multiple return values. 789 // TODO(rmcilroy): support multiple return values.
728 DCHECK_LE(expr->function()->result_size, 1); 790 DCHECK_LE(expr->function()->result_size, 1);
729 Runtime::FunctionId function_id = expr->function()->function_id; 791 Runtime::FunctionId function_id = expr->function()->function_id;
730 builder()->CallRuntime(function_id, first_arg, args->length()); 792 builder()->CallRuntime(function_id, first_arg, args->length());
731 } 793 }
732 794
733 795
734 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { 796 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
735 Visit(expr->expression()); 797 VisitForAccumulatorValue(expr->expression());
736 builder()->LoadUndefined(); 798 builder()->LoadUndefined();
737 } 799 }
738 800
739 801
740 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { 802 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
741 Visit(expr->expression()); 803 VisitForAccumulatorValue(expr->expression());
742 builder()->TypeOf(); 804 builder()->TypeOf();
743 } 805 }
744 806
745 807
746 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { 808 void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
747 Visit(expr->expression()); 809 VisitForAccumulatorValue(expr->expression());
748 builder()->LogicalNot(); 810 builder()->LogicalNot();
749 } 811 }
750 812
751 813
752 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 814 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
753 switch (expr->op()) { 815 switch (expr->op()) {
754 case Token::Value::NOT: 816 case Token::Value::NOT:
755 VisitNot(expr); 817 VisitNot(expr);
756 break; 818 break;
757 case Token::Value::TYPEOF: 819 case Token::Value::TYPEOF:
758 VisitTypeOf(expr); 820 VisitTypeOf(expr);
759 break; 821 break;
760 case Token::Value::VOID: 822 case Token::Value::VOID:
761 VisitVoid(expr); 823 VisitVoid(expr);
762 break; 824 break;
763 case Token::Value::BIT_NOT: 825 case Token::Value::BIT_NOT:
764 case Token::Value::DELETE: 826 case Token::Value::DELETE:
765 UNIMPLEMENTED(); 827 UNIMPLEMENTED();
766 default: 828 default:
767 UNREACHABLE(); 829 UNREACHABLE();
rmcilroy 2015/10/08 16:54:25 AcumulatorSet ?
oth 2015/10/09 12:50:48 Done.
768 } 830 }
769 } 831 }
770 832
771 833
772 void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { 834 void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
773 UNIMPLEMENTED(); 835 UNIMPLEMENTED();
774 } 836 }
775 837
776 838
777 void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) { 839 void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
778 switch (binop->op()) { 840 switch (binop->op()) {
779 case Token::COMMA: 841 case Token::COMMA:
780 case Token::OR: 842 case Token::OR:
781 case Token::AND: 843 case Token::AND:
782 UNIMPLEMENTED(); 844 UNIMPLEMENTED();
783 break; 845 break;
784 default: 846 default:
785 VisitArithmeticExpression(binop); 847 VisitArithmeticExpression(binop);
786 break; 848 break;
787 } 849 }
788 } 850 }
789 851
790 852
791 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { 853 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
792 Token::Value op = expr->op(); 854 TemporaryRegisterScope temporary_register_scope(builder());
793 Expression* left = expr->left(); 855 VisitForRegisterValue(expr->left(), &temporary_register_scope);
794 Expression* right = expr->right(); 856 Register lhs = GetResultRegister();
795 857 VisitForAccumulatorValue(expr->right());
796 TemporaryRegisterScope temporary_register_scope(&builder_); 858 builder()->CompareOperation(expr->op(), lhs, language_mode_strength());
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 } 859 }
804 860
805 861
806 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } 862 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
807 863
808 864
809 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { 865 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
810 UNREACHABLE(); 866 UNREACHABLE();
811 } 867 }
812 868
813 869
814 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { 870 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
815 UNIMPLEMENTED(); 871 UNIMPLEMENTED();
816 } 872 }
817 873
818 874
819 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { 875 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
820 UNIMPLEMENTED(); 876 UNIMPLEMENTED();
821 } 877 }
822 878
823 879
824 void BytecodeGenerator::VisitSuperPropertyReference( 880 void BytecodeGenerator::VisitSuperPropertyReference(
825 SuperPropertyReference* expr) { 881 SuperPropertyReference* expr) {
826 UNIMPLEMENTED(); 882 UNIMPLEMENTED();
827 } 883 }
828 884
829 885
830 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { 886 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) {
831 Token::Value op = binop->op(); 887 TemporaryRegisterScope temporary_register_scope(builder());
832 Expression* left = binop->left(); 888 VisitForRegisterValue(binop->left(), &temporary_register_scope);
833 Expression* right = binop->right(); 889 Register lhs = GetResultRegister();
834 890 VisitForAccumulatorValue(binop->right());
835 TemporaryRegisterScope temporary_register_scope(&builder_); 891 builder()->BinaryOperation(binop->op(), lhs, language_mode_strength());
836 Register temporary = temporary_register_scope.NewRegister(); 892 result_scope()->AccumulatorSet();
837
838 Visit(left);
839 builder()->StoreAccumulatorInRegister(temporary);
840 Visit(right);
841 builder()->BinaryOperation(op, temporary, language_mode_strength());
842 } 893 }
843 894
844 895
896 void BytecodeGenerator::VisitForRegisterValue(
897 Expression* expr, TemporaryRegisterScope* temporary_register_scope) {
898 RegisterResultScope register_scope(this, temporary_register_scope);
899 Visit(expr);
900 }
901
902
903 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
904 AccumulatorResultScope accumulator_scope(this);
905 Visit(expr);
906 }
907
908
909 void BytecodeGenerator::SetResultRegister(Register reg) {
910 DCHECK(result_register_.IsNothing());
911 result_register_ = Just<Register>(reg);
912 }
913
914
915 Register BytecodeGenerator::GetResultRegister() {
916 DCHECK(result_register_.IsJust());
917 Register reg = result_register_.FromJust();
918 DropResultRegister();
919 return reg;
920 }
921
922
923 void BytecodeGenerator::DropResultRegister() {
924 result_register_ = Nothing<Register>();
925 }
926
927
845 LanguageMode BytecodeGenerator::language_mode() const { 928 LanguageMode BytecodeGenerator::language_mode() const {
846 return info()->language_mode(); 929 return info()->language_mode();
847 } 930 }
848 931
849 932
850 Strength BytecodeGenerator::language_mode_strength() const { 933 Strength BytecodeGenerator::language_mode_strength() const {
851 return strength(language_mode()); 934 return strength(language_mode());
852 } 935 }
853 936
854 937
855 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 938 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
856 return info()->feedback_vector()->GetIndex(slot); 939 return info()->feedback_vector()->GetIndex(slot);
857 } 940 }
858 941
859 942
860 Register BytecodeGenerator::current_context() const { return current_context_; } 943 Register BytecodeGenerator::current_context() const { return current_context_; }
861 944
862 } // namespace interpreter 945 } // namespace interpreter
863 } // namespace internal 946 } // namespace internal
864 } // namespace v8 947 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698