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