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