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