| 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 "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 #include "src/compiler.h" | 9 #include "src/compiler.h" |
| 10 #include "src/interpreter/bytecode-register-allocator.h" | 10 #include "src/interpreter/bytecode-register-allocator.h" |
| 11 #include "src/interpreter/control-flow-builders.h" | 11 #include "src/interpreter/control-flow-builders.h" |
| 12 #include "src/objects.h" | 12 #include "src/objects.h" |
| 13 #include "src/parsing/parser.h" | 13 #include "src/parsing/parser.h" |
| 14 #include "src/parsing/token.h" | 14 #include "src/parsing/token.h" |
| 15 | 15 |
| 16 namespace v8 { | 16 namespace v8 { |
| 17 namespace internal { | 17 namespace internal { |
| 18 namespace interpreter { | 18 namespace interpreter { |
| 19 | 19 |
| 20 | |
| 21 // Scoped class tracking context objects created by the visitor. Represents | 20 // Scoped class tracking context objects created by the visitor. Represents |
| 22 // mutations of the context chain within the function body, allowing pushing and | 21 // mutations of the context chain within the function body, allowing pushing and |
| 23 // popping of the current {context_register} during visitation. | 22 // popping of the current {context_register} during visitation. |
| 24 class BytecodeGenerator::ContextScope BASE_EMBEDDED { | 23 class BytecodeGenerator::ContextScope BASE_EMBEDDED { |
| 25 public: | 24 public: |
| 26 ContextScope(BytecodeGenerator* generator, Scope* scope, | 25 ContextScope(BytecodeGenerator* generator, Scope* scope, |
| 27 bool should_pop_context = true) | 26 bool should_pop_context = true) |
| 28 : generator_(generator), | 27 : generator_(generator), |
| 29 scope_(scope), | 28 scope_(scope), |
| 30 outer_(generator_->execution_context()), | 29 outer_(generator_->execution_context()), |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 void set_register(Register reg) { register_ = reg; } | 80 void set_register(Register reg) { register_ = reg; } |
| 82 | 81 |
| 83 BytecodeGenerator* generator_; | 82 BytecodeGenerator* generator_; |
| 84 Scope* scope_; | 83 Scope* scope_; |
| 85 ContextScope* outer_; | 84 ContextScope* outer_; |
| 86 Register register_; | 85 Register register_; |
| 87 int depth_; | 86 int depth_; |
| 88 bool should_pop_context_; | 87 bool should_pop_context_; |
| 89 }; | 88 }; |
| 90 | 89 |
| 91 | |
| 92 // Scoped class for tracking control statements entered by the | 90 // Scoped class for tracking control statements entered by the |
| 93 // visitor. The pattern derives AstGraphBuilder::ControlScope. | 91 // visitor. The pattern derives AstGraphBuilder::ControlScope. |
| 94 class BytecodeGenerator::ControlScope BASE_EMBEDDED { | 92 class BytecodeGenerator::ControlScope BASE_EMBEDDED { |
| 95 public: | 93 public: |
| 96 explicit ControlScope(BytecodeGenerator* generator) | 94 explicit ControlScope(BytecodeGenerator* generator) |
| 97 : generator_(generator), outer_(generator->execution_control()), | 95 : generator_(generator), outer_(generator->execution_control()), |
| 98 context_(generator->execution_context()) { | 96 context_(generator->execution_context()) { |
| 99 generator_->set_execution_control(this); | 97 generator_->set_execution_control(this); |
| 100 } | 98 } |
| 101 virtual ~ControlScope() { generator_->set_execution_control(outer()); } | 99 virtual ~ControlScope() { generator_->set_execution_control(outer()); } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 117 ContextScope* context() const { return context_; } | 115 ContextScope* context() const { return context_; } |
| 118 | 116 |
| 119 private: | 117 private: |
| 120 BytecodeGenerator* generator_; | 118 BytecodeGenerator* generator_; |
| 121 ControlScope* outer_; | 119 ControlScope* outer_; |
| 122 ContextScope* context_; | 120 ContextScope* context_; |
| 123 | 121 |
| 124 DISALLOW_COPY_AND_ASSIGN(ControlScope); | 122 DISALLOW_COPY_AND_ASSIGN(ControlScope); |
| 125 }; | 123 }; |
| 126 | 124 |
| 127 | |
| 128 // Helper class for a try-finally control scope. It can record intercepted | 125 // Helper class for a try-finally control scope. It can record intercepted |
| 129 // control-flow commands that cause entry into a finally-block, and re-apply | 126 // control-flow commands that cause entry into a finally-block, and re-apply |
| 130 // them after again leaving that block. Special tokens are used to identify | 127 // them after again leaving that block. Special tokens are used to identify |
| 131 // paths going through the finally-block to dispatch after leaving the block. | 128 // paths going through the finally-block to dispatch after leaving the block. |
| 132 class BytecodeGenerator::ControlScope::DeferredCommands final { | 129 class BytecodeGenerator::ControlScope::DeferredCommands final { |
| 133 public: | 130 public: |
| 134 DeferredCommands(BytecodeGenerator* generator, Register token_register, | 131 DeferredCommands(BytecodeGenerator* generator, Register token_register, |
| 135 Register result_register) | 132 Register result_register) |
| 136 : generator_(generator), | 133 : generator_(generator), |
| 137 deferred_(generator->zone()), | 134 deferred_(generator->zone()), |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 BytecodeArrayBuilder* builder() { return generator_->builder(); } | 193 BytecodeArrayBuilder* builder() { return generator_->builder(); } |
| 197 ControlScope* execution_control() { return generator_->execution_control(); } | 194 ControlScope* execution_control() { return generator_->execution_control(); } |
| 198 | 195 |
| 199 private: | 196 private: |
| 200 BytecodeGenerator* generator_; | 197 BytecodeGenerator* generator_; |
| 201 ZoneVector<Entry> deferred_; | 198 ZoneVector<Entry> deferred_; |
| 202 Register token_register_; | 199 Register token_register_; |
| 203 Register result_register_; | 200 Register result_register_; |
| 204 }; | 201 }; |
| 205 | 202 |
| 206 | |
| 207 // Scoped class for dealing with control flow reaching the function level. | 203 // Scoped class for dealing with control flow reaching the function level. |
| 208 class BytecodeGenerator::ControlScopeForTopLevel final | 204 class BytecodeGenerator::ControlScopeForTopLevel final |
| 209 : public BytecodeGenerator::ControlScope { | 205 : public BytecodeGenerator::ControlScope { |
| 210 public: | 206 public: |
| 211 explicit ControlScopeForTopLevel(BytecodeGenerator* generator) | 207 explicit ControlScopeForTopLevel(BytecodeGenerator* generator) |
| 212 : ControlScope(generator) {} | 208 : ControlScope(generator) {} |
| 213 | 209 |
| 214 protected: | 210 protected: |
| 215 bool Execute(Command command, Statement* statement) override { | 211 bool Execute(Command command, Statement* statement) override { |
| 216 switch (command) { | 212 switch (command) { |
| 217 case CMD_BREAK: // We should never see break/continue in top-level. | 213 case CMD_BREAK: // We should never see break/continue in top-level. |
| 218 case CMD_CONTINUE: | 214 case CMD_CONTINUE: |
| 219 UNREACHABLE(); | 215 UNREACHABLE(); |
| 220 case CMD_RETURN: | 216 case CMD_RETURN: |
| 221 generator()->builder()->SetReturnPosition(); | 217 generator()->builder()->SetReturnPosition(); |
| 222 generator()->builder()->Return(); | 218 generator()->builder()->Return(); |
| 223 return true; | 219 return true; |
| 224 case CMD_RETHROW: | 220 case CMD_RETHROW: |
| 225 generator()->builder()->ReThrow(); | 221 generator()->builder()->ReThrow(); |
| 226 return true; | 222 return true; |
| 227 } | 223 } |
| 228 return false; | 224 return false; |
| 229 } | 225 } |
| 230 }; | 226 }; |
| 231 | 227 |
| 232 | |
| 233 // Scoped class for enabling break inside blocks and switch blocks. | 228 // Scoped class for enabling break inside blocks and switch blocks. |
| 234 class BytecodeGenerator::ControlScopeForBreakable final | 229 class BytecodeGenerator::ControlScopeForBreakable final |
| 235 : public BytecodeGenerator::ControlScope { | 230 : public BytecodeGenerator::ControlScope { |
| 236 public: | 231 public: |
| 237 ControlScopeForBreakable(BytecodeGenerator* generator, | 232 ControlScopeForBreakable(BytecodeGenerator* generator, |
| 238 BreakableStatement* statement, | 233 BreakableStatement* statement, |
| 239 BreakableControlFlowBuilder* control_builder) | 234 BreakableControlFlowBuilder* control_builder) |
| 240 : ControlScope(generator), | 235 : ControlScope(generator), |
| 241 statement_(statement), | 236 statement_(statement), |
| 242 control_builder_(control_builder) {} | 237 control_builder_(control_builder) {} |
| (...skipping 11 matching lines...) Expand all Loading... |
| 254 break; | 249 break; |
| 255 } | 250 } |
| 256 return false; | 251 return false; |
| 257 } | 252 } |
| 258 | 253 |
| 259 private: | 254 private: |
| 260 Statement* statement_; | 255 Statement* statement_; |
| 261 BreakableControlFlowBuilder* control_builder_; | 256 BreakableControlFlowBuilder* control_builder_; |
| 262 }; | 257 }; |
| 263 | 258 |
| 264 | |
| 265 // Scoped class for enabling 'break' and 'continue' in iteration | 259 // Scoped class for enabling 'break' and 'continue' in iteration |
| 266 // constructs, e.g. do...while, while..., for... | 260 // constructs, e.g. do...while, while..., for... |
| 267 class BytecodeGenerator::ControlScopeForIteration final | 261 class BytecodeGenerator::ControlScopeForIteration final |
| 268 : public BytecodeGenerator::ControlScope { | 262 : public BytecodeGenerator::ControlScope { |
| 269 public: | 263 public: |
| 270 ControlScopeForIteration(BytecodeGenerator* generator, | 264 ControlScopeForIteration(BytecodeGenerator* generator, |
| 271 IterationStatement* statement, | 265 IterationStatement* statement, |
| 272 LoopBuilder* loop_builder) | 266 LoopBuilder* loop_builder) |
| 273 : ControlScope(generator), | 267 : ControlScope(generator), |
| 274 statement_(statement), | 268 statement_(statement), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 289 break; | 283 break; |
| 290 } | 284 } |
| 291 return false; | 285 return false; |
| 292 } | 286 } |
| 293 | 287 |
| 294 private: | 288 private: |
| 295 Statement* statement_; | 289 Statement* statement_; |
| 296 LoopBuilder* loop_builder_; | 290 LoopBuilder* loop_builder_; |
| 297 }; | 291 }; |
| 298 | 292 |
| 299 | |
| 300 // Scoped class for enabling 'throw' in try-catch constructs. | 293 // Scoped class for enabling 'throw' in try-catch constructs. |
| 301 class BytecodeGenerator::ControlScopeForTryCatch final | 294 class BytecodeGenerator::ControlScopeForTryCatch final |
| 302 : public BytecodeGenerator::ControlScope { | 295 : public BytecodeGenerator::ControlScope { |
| 303 public: | 296 public: |
| 304 ControlScopeForTryCatch(BytecodeGenerator* generator, | 297 ControlScopeForTryCatch(BytecodeGenerator* generator, |
| 305 TryCatchBuilder* try_catch_builder) | 298 TryCatchBuilder* try_catch_builder) |
| 306 : ControlScope(generator) { | 299 : ControlScope(generator) { |
| 307 generator->try_catch_nesting_level_++; | 300 generator->try_catch_nesting_level_++; |
| 308 } | 301 } |
| 309 virtual ~ControlScopeForTryCatch() { | 302 virtual ~ControlScopeForTryCatch() { |
| 310 generator()->try_catch_nesting_level_--; | 303 generator()->try_catch_nesting_level_--; |
| 311 } | 304 } |
| 312 | 305 |
| 313 protected: | 306 protected: |
| 314 bool Execute(Command command, Statement* statement) override { | 307 bool Execute(Command command, Statement* statement) override { |
| 315 switch (command) { | 308 switch (command) { |
| 316 case CMD_BREAK: | 309 case CMD_BREAK: |
| 317 case CMD_CONTINUE: | 310 case CMD_CONTINUE: |
| 318 case CMD_RETURN: | 311 case CMD_RETURN: |
| 319 break; | 312 break; |
| 320 case CMD_RETHROW: | 313 case CMD_RETHROW: |
| 321 generator()->builder()->ReThrow(); | 314 generator()->builder()->ReThrow(); |
| 322 return true; | 315 return true; |
| 323 } | 316 } |
| 324 return false; | 317 return false; |
| 325 } | 318 } |
| 326 }; | 319 }; |
| 327 | 320 |
| 328 | |
| 329 // Scoped class for enabling control flow through try-finally constructs. | 321 // Scoped class for enabling control flow through try-finally constructs. |
| 330 class BytecodeGenerator::ControlScopeForTryFinally final | 322 class BytecodeGenerator::ControlScopeForTryFinally final |
| 331 : public BytecodeGenerator::ControlScope { | 323 : public BytecodeGenerator::ControlScope { |
| 332 public: | 324 public: |
| 333 ControlScopeForTryFinally(BytecodeGenerator* generator, | 325 ControlScopeForTryFinally(BytecodeGenerator* generator, |
| 334 TryFinallyBuilder* try_finally_builder, | 326 TryFinallyBuilder* try_finally_builder, |
| 335 DeferredCommands* commands) | 327 DeferredCommands* commands) |
| 336 : ControlScope(generator), | 328 : ControlScope(generator), |
| 337 try_finally_builder_(try_finally_builder), | 329 try_finally_builder_(try_finally_builder), |
| 338 commands_(commands) { | 330 commands_(commands) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 354 return true; | 346 return true; |
| 355 } | 347 } |
| 356 return false; | 348 return false; |
| 357 } | 349 } |
| 358 | 350 |
| 359 private: | 351 private: |
| 360 TryFinallyBuilder* try_finally_builder_; | 352 TryFinallyBuilder* try_finally_builder_; |
| 361 DeferredCommands* commands_; | 353 DeferredCommands* commands_; |
| 362 }; | 354 }; |
| 363 | 355 |
| 364 | |
| 365 void BytecodeGenerator::ControlScope::PerformCommand(Command command, | 356 void BytecodeGenerator::ControlScope::PerformCommand(Command command, |
| 366 Statement* statement) { | 357 Statement* statement) { |
| 367 ControlScope* current = this; | 358 ControlScope* current = this; |
| 368 ContextScope* context = generator()->execution_context(); | 359 ContextScope* context = generator()->execution_context(); |
| 369 // Pop context to the expected depth but do not pop the outermost context. | 360 // Pop context to the expected depth but do not pop the outermost context. |
| 370 if (context != current->context() && context->ShouldPopContext()) { | 361 if (context != current->context() && context->ShouldPopContext()) { |
| 371 generator()->builder()->PopContext(current->context()->reg()); | 362 generator()->builder()->PopContext(current->context()->reg()); |
| 372 } | 363 } |
| 373 do { | 364 do { |
| 374 if (current->Execute(command, statement)) { | 365 if (current->Execute(command, statement)) { |
| 375 return; | 366 return; |
| 376 } | 367 } |
| 377 current = current->outer(); | 368 current = current->outer(); |
| 378 if (current->context() != context) { | 369 if (current->context() != context) { |
| 379 // Pop context to the expected depth. | 370 // Pop context to the expected depth. |
| 380 // TODO(rmcilroy): Only emit a single context pop. | 371 // TODO(rmcilroy): Only emit a single context pop. |
| 381 generator()->builder()->PopContext(current->context()->reg()); | 372 generator()->builder()->PopContext(current->context()->reg()); |
| 382 } | 373 } |
| 383 } while (current != nullptr); | 374 } while (current != nullptr); |
| 384 UNREACHABLE(); | 375 UNREACHABLE(); |
| 385 } | 376 } |
| 386 | 377 |
| 387 | |
| 388 class BytecodeGenerator::RegisterAllocationScope { | 378 class BytecodeGenerator::RegisterAllocationScope { |
| 389 public: | 379 public: |
| 390 explicit RegisterAllocationScope(BytecodeGenerator* generator) | 380 explicit RegisterAllocationScope(BytecodeGenerator* generator) |
| 391 : generator_(generator), | 381 : generator_(generator), |
| 392 outer_(generator->register_allocator()), | 382 outer_(generator->register_allocator()), |
| 393 allocator_(builder()->zone(), | 383 allocator_(builder()->zone(), |
| 394 builder()->temporary_register_allocator()) { | 384 builder()->temporary_register_allocator()) { |
| 395 generator_->set_register_allocator(this); | 385 generator_->set_register_allocator(this); |
| 396 } | 386 } |
| 397 | 387 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 BytecodeGenerator* generator() const { return generator_; } | 425 BytecodeGenerator* generator() const { return generator_; } |
| 436 BytecodeArrayBuilder* builder() const { return generator_->builder(); } | 426 BytecodeArrayBuilder* builder() const { return generator_->builder(); } |
| 437 | 427 |
| 438 BytecodeGenerator* generator_; | 428 BytecodeGenerator* generator_; |
| 439 RegisterAllocationScope* outer_; | 429 RegisterAllocationScope* outer_; |
| 440 BytecodeRegisterAllocator allocator_; | 430 BytecodeRegisterAllocator allocator_; |
| 441 | 431 |
| 442 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope); | 432 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope); |
| 443 }; | 433 }; |
| 444 | 434 |
| 445 | |
| 446 // Scoped base class for determining where the result of an expression | 435 // Scoped base class for determining where the result of an expression |
| 447 // is stored. | 436 // is stored. |
| 448 class BytecodeGenerator::ExpressionResultScope { | 437 class BytecodeGenerator::ExpressionResultScope { |
| 449 public: | 438 public: |
| 450 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind) | 439 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind) |
| 451 : generator_(generator), | 440 : generator_(generator), |
| 452 kind_(kind), | 441 kind_(kind), |
| 453 outer_(generator->execution_result()), | 442 outer_(generator->execution_result()), |
| 454 allocator_(generator), | 443 allocator_(generator), |
| 455 result_identified_(false) { | 444 result_identified_(false) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 483 private: | 472 private: |
| 484 BytecodeGenerator* generator_; | 473 BytecodeGenerator* generator_; |
| 485 Expression::Context kind_; | 474 Expression::Context kind_; |
| 486 ExpressionResultScope* outer_; | 475 ExpressionResultScope* outer_; |
| 487 RegisterAllocationScope allocator_; | 476 RegisterAllocationScope allocator_; |
| 488 bool result_identified_; | 477 bool result_identified_; |
| 489 | 478 |
| 490 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); | 479 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); |
| 491 }; | 480 }; |
| 492 | 481 |
| 493 | |
| 494 // Scoped class used when the result of the current expression is not | 482 // Scoped class used when the result of the current expression is not |
| 495 // expected to produce a result. | 483 // expected to produce a result. |
| 496 class BytecodeGenerator::EffectResultScope final | 484 class BytecodeGenerator::EffectResultScope final |
| 497 : public ExpressionResultScope { | 485 : public ExpressionResultScope { |
| 498 public: | 486 public: |
| 499 explicit EffectResultScope(BytecodeGenerator* generator) | 487 explicit EffectResultScope(BytecodeGenerator* generator) |
| 500 : ExpressionResultScope(generator, Expression::kEffect) { | 488 : ExpressionResultScope(generator, Expression::kEffect) { |
| 501 set_result_identified(); | 489 set_result_identified(); |
| 502 } | 490 } |
| 503 | 491 |
| 504 virtual void SetResultInAccumulator() {} | 492 virtual void SetResultInAccumulator() {} |
| 505 virtual void SetResultInRegister(Register reg) {} | 493 virtual void SetResultInRegister(Register reg) {} |
| 506 }; | 494 }; |
| 507 | 495 |
| 508 | |
| 509 // Scoped class used when the result of the current expression to be | 496 // Scoped class used when the result of the current expression to be |
| 510 // evaluated should go into the interpreter's accumulator register. | 497 // evaluated should go into the interpreter's accumulator register. |
| 511 class BytecodeGenerator::AccumulatorResultScope final | 498 class BytecodeGenerator::AccumulatorResultScope final |
| 512 : public ExpressionResultScope { | 499 : public ExpressionResultScope { |
| 513 public: | 500 public: |
| 514 explicit AccumulatorResultScope(BytecodeGenerator* generator) | 501 explicit AccumulatorResultScope(BytecodeGenerator* generator) |
| 515 : ExpressionResultScope(generator, Expression::kValue) {} | 502 : ExpressionResultScope(generator, Expression::kValue) {} |
| 516 | 503 |
| 517 virtual void SetResultInAccumulator() { set_result_identified(); } | 504 virtual void SetResultInAccumulator() { set_result_identified(); } |
| 518 | 505 |
| 519 virtual void SetResultInRegister(Register reg) { | 506 virtual void SetResultInRegister(Register reg) { |
| 520 builder()->LoadAccumulatorWithRegister(reg); | 507 builder()->LoadAccumulatorWithRegister(reg); |
| 521 set_result_identified(); | 508 set_result_identified(); |
| 522 } | 509 } |
| 523 }; | 510 }; |
| 524 | 511 |
| 525 | |
| 526 // Scoped class used when the result of the current expression to be | 512 // Scoped class used when the result of the current expression to be |
| 527 // evaluated should go into an interpreter register. | 513 // evaluated should go into an interpreter register. |
| 528 class BytecodeGenerator::RegisterResultScope final | 514 class BytecodeGenerator::RegisterResultScope final |
| 529 : public ExpressionResultScope { | 515 : public ExpressionResultScope { |
| 530 public: | 516 public: |
| 531 explicit RegisterResultScope(BytecodeGenerator* generator) | 517 explicit RegisterResultScope(BytecodeGenerator* generator) |
| 532 : ExpressionResultScope(generator, Expression::kValue) {} | 518 : ExpressionResultScope(generator, Expression::kValue) {} |
| 533 | 519 |
| 534 virtual void SetResultInAccumulator() { | 520 virtual void SetResultInAccumulator() { |
| 535 result_register_ = allocator()->outer()->NewRegister(); | 521 result_register_ = allocator()->outer()->NewRegister(); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 // contain jumps to unbound labels (resume points that will never be used). | 593 // contain jumps to unbound labels (resume points that will never be used). |
| 608 // We bind these now. | 594 // We bind these now. |
| 609 for (auto& label : generator_resume_points_) { | 595 for (auto& label : generator_resume_points_) { |
| 610 if (!label.is_bound()) builder()->Bind(&label); | 596 if (!label.is_bound()) builder()->Bind(&label); |
| 611 } | 597 } |
| 612 | 598 |
| 613 builder()->EnsureReturn(); | 599 builder()->EnsureReturn(); |
| 614 return builder()->ToBytecodeArray(); | 600 return builder()->ToBytecodeArray(); |
| 615 } | 601 } |
| 616 | 602 |
| 617 | |
| 618 void BytecodeGenerator::MakeBytecodeBody() { | 603 void BytecodeGenerator::MakeBytecodeBody() { |
| 619 // Build the arguments object if it is used. | 604 // Build the arguments object if it is used. |
| 620 VisitArgumentsObject(scope()->arguments()); | 605 VisitArgumentsObject(scope()->arguments()); |
| 621 | 606 |
| 622 // Build rest arguments array if it is used. | 607 // Build rest arguments array if it is used. |
| 623 int rest_index; | 608 int rest_index; |
| 624 Variable* rest_parameter = scope()->rest_parameter(&rest_index); | 609 Variable* rest_parameter = scope()->rest_parameter(&rest_index); |
| 625 VisitRestArgumentsArray(rest_parameter); | 610 VisitRestArgumentsArray(rest_parameter); |
| 626 | 611 |
| 627 // Build assignment to {.this_function} variable if it is used. | 612 // Build assignment to {.this_function} variable if it is used. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 // Visit declarations and statements. | 707 // Visit declarations and statements. |
| 723 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { | 708 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) { |
| 724 VisitNewLocalBlockContext(stmt->scope()); | 709 VisitNewLocalBlockContext(stmt->scope()); |
| 725 ContextScope scope(this, stmt->scope()); | 710 ContextScope scope(this, stmt->scope()); |
| 726 VisitBlockDeclarationsAndStatements(stmt); | 711 VisitBlockDeclarationsAndStatements(stmt); |
| 727 } else { | 712 } else { |
| 728 VisitBlockDeclarationsAndStatements(stmt); | 713 VisitBlockDeclarationsAndStatements(stmt); |
| 729 } | 714 } |
| 730 } | 715 } |
| 731 | 716 |
| 732 | |
| 733 void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) { | 717 void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) { |
| 734 BlockBuilder block_builder(builder()); | 718 BlockBuilder block_builder(builder()); |
| 735 ControlScopeForBreakable execution_control(this, stmt, &block_builder); | 719 ControlScopeForBreakable execution_control(this, stmt, &block_builder); |
| 736 if (stmt->scope() != nullptr) { | 720 if (stmt->scope() != nullptr) { |
| 737 VisitDeclarations(stmt->scope()->declarations()); | 721 VisitDeclarations(stmt->scope()->declarations()); |
| 738 } | 722 } |
| 739 VisitStatements(stmt->statements()); | 723 VisitStatements(stmt->statements()); |
| 740 if (stmt->labels() != nullptr) block_builder.EndBlock(); | 724 if (stmt->labels() != nullptr) block_builder.EndBlock(); |
| 741 } | 725 } |
| 742 | 726 |
| 743 | |
| 744 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { | 727 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { |
| 745 Variable* variable = decl->proxy()->var(); | 728 Variable* variable = decl->proxy()->var(); |
| 746 VariableMode mode = decl->mode(); | 729 VariableMode mode = decl->mode(); |
| 747 // Const and let variables are initialized with the hole so that we can | 730 // Const and let variables are initialized with the hole so that we can |
| 748 // check that they are only assigned once. | 731 // check that they are only assigned once. |
| 749 bool hole_init = mode == CONST || mode == LET; | 732 bool hole_init = mode == CONST || mode == LET; |
| 750 switch (variable->location()) { | 733 switch (variable->location()) { |
| 751 case VariableLocation::GLOBAL: | 734 case VariableLocation::GLOBAL: |
| 752 case VariableLocation::UNALLOCATED: | 735 case VariableLocation::UNALLOCATED: |
| 753 DCHECK(!variable->binding_needs_init()); | 736 DCHECK(!variable->binding_needs_init()); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 } | 778 } |
| 796 builder() | 779 builder() |
| 797 ->LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes())) | 780 ->LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes())) |
| 798 .StoreAccumulatorInRegister(attributes) | 781 .StoreAccumulatorInRegister(attributes) |
| 799 .CallRuntime(Runtime::kDeclareLookupSlot, name, 3); | 782 .CallRuntime(Runtime::kDeclareLookupSlot, name, 3); |
| 800 break; | 783 break; |
| 801 } | 784 } |
| 802 } | 785 } |
| 803 } | 786 } |
| 804 | 787 |
| 805 | |
| 806 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 788 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
| 807 Variable* variable = decl->proxy()->var(); | 789 Variable* variable = decl->proxy()->var(); |
| 808 switch (variable->location()) { | 790 switch (variable->location()) { |
| 809 case VariableLocation::GLOBAL: | 791 case VariableLocation::GLOBAL: |
| 810 case VariableLocation::UNALLOCATED: { | 792 case VariableLocation::UNALLOCATED: { |
| 811 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo( | 793 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo( |
| 812 decl->fun(), info()->script(), info()); | 794 decl->fun(), info()->script(), info()); |
| 813 // Check for stack-overflow exception. | 795 // Check for stack-overflow exception. |
| 814 if (function.is_null()) return SetStackOverflow(); | 796 if (function.is_null()) return SetStackOverflow(); |
| 815 globals()->push_back(variable->name()); | 797 globals()->push_back(variable->name()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 842 VisitForAccumulatorValue(decl->fun()); | 824 VisitForAccumulatorValue(decl->fun()); |
| 843 builder() | 825 builder() |
| 844 ->StoreAccumulatorInRegister(literal) | 826 ->StoreAccumulatorInRegister(literal) |
| 845 .LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes())) | 827 .LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes())) |
| 846 .StoreAccumulatorInRegister(attributes) | 828 .StoreAccumulatorInRegister(attributes) |
| 847 .CallRuntime(Runtime::kDeclareLookupSlot, name, 3); | 829 .CallRuntime(Runtime::kDeclareLookupSlot, name, 3); |
| 848 } | 830 } |
| 849 } | 831 } |
| 850 } | 832 } |
| 851 | 833 |
| 852 | |
| 853 void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) { | 834 void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) { |
| 854 UNIMPLEMENTED(); | 835 UNIMPLEMENTED(); |
| 855 } | 836 } |
| 856 | 837 |
| 857 | |
| 858 void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) { | 838 void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) { |
| 859 UNIMPLEMENTED(); | 839 UNIMPLEMENTED(); |
| 860 } | 840 } |
| 861 | 841 |
| 862 | |
| 863 void BytecodeGenerator::VisitDeclarations( | 842 void BytecodeGenerator::VisitDeclarations( |
| 864 ZoneList<Declaration*>* declarations) { | 843 ZoneList<Declaration*>* declarations) { |
| 865 RegisterAllocationScope register_scope(this); | 844 RegisterAllocationScope register_scope(this); |
| 866 DCHECK(globals()->empty()); | 845 DCHECK(globals()->empty()); |
| 867 for (int i = 0; i < declarations->length(); i++) { | 846 for (int i = 0; i < declarations->length(); i++) { |
| 868 RegisterAllocationScope register_scope(this); | 847 RegisterAllocationScope register_scope(this); |
| 869 Visit(declarations->at(i)); | 848 Visit(declarations->at(i)); |
| 870 } | 849 } |
| 871 if (globals()->empty()) return; | 850 if (globals()->empty()) return; |
| 872 int array_index = 0; | 851 int array_index = 0; |
| 873 Handle<FixedArray> data = isolate()->factory()->NewFixedArray( | 852 Handle<FixedArray> data = isolate()->factory()->NewFixedArray( |
| 874 static_cast<int>(globals()->size()), TENURED); | 853 static_cast<int>(globals()->size()), TENURED); |
| 875 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj); | 854 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj); |
| 876 int encoded_flags = info()->GetDeclareGlobalsFlags(); | 855 int encoded_flags = info()->GetDeclareGlobalsFlags(); |
| 877 | 856 |
| 878 Register pairs = register_allocator()->NewRegister(); | 857 Register pairs = register_allocator()->NewRegister(); |
| 879 builder()->LoadLiteral(data); | 858 builder()->LoadLiteral(data); |
| 880 builder()->StoreAccumulatorInRegister(pairs); | 859 builder()->StoreAccumulatorInRegister(pairs); |
| 881 | 860 |
| 882 Register flags = register_allocator()->NewRegister(); | 861 Register flags = register_allocator()->NewRegister(); |
| 883 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); | 862 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); |
| 884 builder()->StoreAccumulatorInRegister(flags); | 863 builder()->StoreAccumulatorInRegister(flags); |
| 885 DCHECK(flags.index() == pairs.index() + 1); | 864 DCHECK(flags.index() == pairs.index() + 1); |
| 886 | 865 |
| 887 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); | 866 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); |
| 888 globals()->clear(); | 867 globals()->clear(); |
| 889 } | 868 } |
| 890 | 869 |
| 891 | |
| 892 void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { | 870 void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) { |
| 893 for (int i = 0; i < statements->length(); i++) { | 871 for (int i = 0; i < statements->length(); i++) { |
| 894 // Allocate an outer register allocations scope for the statement. | 872 // Allocate an outer register allocations scope for the statement. |
| 895 RegisterAllocationScope allocation_scope(this); | 873 RegisterAllocationScope allocation_scope(this); |
| 896 Statement* stmt = statements->at(i); | 874 Statement* stmt = statements->at(i); |
| 897 Visit(stmt); | 875 Visit(stmt); |
| 898 if (stmt->IsJump()) break; | 876 if (stmt->IsJump()) break; |
| 899 } | 877 } |
| 900 } | 878 } |
| 901 | 879 |
| 902 | |
| 903 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 880 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
| 904 builder()->SetStatementPosition(stmt); | 881 builder()->SetStatementPosition(stmt); |
| 905 VisitForEffect(stmt->expression()); | 882 VisitForEffect(stmt->expression()); |
| 906 } | 883 } |
| 907 | 884 |
| 908 | |
| 909 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 885 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
| 910 } | 886 } |
| 911 | 887 |
| 912 | |
| 913 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { | 888 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { |
| 914 builder()->SetStatementPosition(stmt); | 889 builder()->SetStatementPosition(stmt); |
| 915 BytecodeLabel else_label, end_label; | 890 BytecodeLabel else_label, end_label; |
| 916 if (stmt->condition()->ToBooleanIsTrue()) { | 891 if (stmt->condition()->ToBooleanIsTrue()) { |
| 917 // Generate then block unconditionally as always true. | 892 // Generate then block unconditionally as always true. |
| 918 Visit(stmt->then_statement()); | 893 Visit(stmt->then_statement()); |
| 919 } else if (stmt->condition()->ToBooleanIsFalse()) { | 894 } else if (stmt->condition()->ToBooleanIsFalse()) { |
| 920 // Generate else block unconditionally if it exists. | 895 // Generate else block unconditionally if it exists. |
| 921 if (stmt->HasElseStatement()) { | 896 if (stmt->HasElseStatement()) { |
| 922 Visit(stmt->else_statement()); | 897 Visit(stmt->else_statement()); |
| 923 } | 898 } |
| 924 } else { | 899 } else { |
| 925 // TODO(oth): If then statement is BreakStatement or | 900 // TODO(oth): If then statement is BreakStatement or |
| 926 // ContinueStatement we can reduce number of generated | 901 // ContinueStatement we can reduce number of generated |
| 927 // jump/jump_ifs here. See BasicLoops test. | 902 // jump/jump_ifs here. See BasicLoops test. |
| 928 VisitForAccumulatorValue(stmt->condition()); | 903 VisitForAccumulatorValue(stmt->condition()); |
| 929 builder()->JumpIfFalse(&else_label); | 904 builder()->JumpIfFalse(&else_label); |
| 930 Visit(stmt->then_statement()); | 905 Visit(stmt->then_statement()); |
| 931 if (stmt->HasElseStatement()) { | 906 if (stmt->HasElseStatement()) { |
| 932 builder()->Jump(&end_label); | 907 builder()->Jump(&end_label); |
| 933 builder()->Bind(&else_label); | 908 builder()->Bind(&else_label); |
| 934 Visit(stmt->else_statement()); | 909 Visit(stmt->else_statement()); |
| 935 } else { | 910 } else { |
| 936 builder()->Bind(&else_label); | 911 builder()->Bind(&else_label); |
| 937 } | 912 } |
| 938 builder()->Bind(&end_label); | 913 builder()->Bind(&end_label); |
| 939 } | 914 } |
| 940 } | 915 } |
| 941 | 916 |
| 942 | |
| 943 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( | 917 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( |
| 944 SloppyBlockFunctionStatement* stmt) { | 918 SloppyBlockFunctionStatement* stmt) { |
| 945 Visit(stmt->statement()); | 919 Visit(stmt->statement()); |
| 946 } | 920 } |
| 947 | 921 |
| 948 | |
| 949 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 922 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { |
| 950 builder()->SetStatementPosition(stmt); | 923 builder()->SetStatementPosition(stmt); |
| 951 execution_control()->Continue(stmt->target()); | 924 execution_control()->Continue(stmt->target()); |
| 952 } | 925 } |
| 953 | 926 |
| 954 | |
| 955 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 927 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
| 956 builder()->SetStatementPosition(stmt); | 928 builder()->SetStatementPosition(stmt); |
| 957 execution_control()->Break(stmt->target()); | 929 execution_control()->Break(stmt->target()); |
| 958 } | 930 } |
| 959 | 931 |
| 960 | |
| 961 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 932 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
| 962 builder()->SetStatementPosition(stmt); | 933 builder()->SetStatementPosition(stmt); |
| 963 VisitForAccumulatorValue(stmt->expression()); | 934 VisitForAccumulatorValue(stmt->expression()); |
| 964 execution_control()->ReturnAccumulator(); | 935 execution_control()->ReturnAccumulator(); |
| 965 } | 936 } |
| 966 | 937 |
| 967 | |
| 968 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 938 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
| 969 builder()->SetStatementPosition(stmt); | 939 builder()->SetStatementPosition(stmt); |
| 970 VisitForAccumulatorValue(stmt->expression()); | 940 VisitForAccumulatorValue(stmt->expression()); |
| 971 builder()->CastAccumulatorToJSObject(); | 941 builder()->CastAccumulatorToJSObject(); |
| 972 VisitNewLocalWithContext(); | 942 VisitNewLocalWithContext(); |
| 973 VisitInScope(stmt->statement(), stmt->scope()); | 943 VisitInScope(stmt->statement(), stmt->scope()); |
| 974 } | 944 } |
| 975 | 945 |
| 976 | |
| 977 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 946 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| 978 // We need this scope because we visit for register values. We have to | 947 // We need this scope because we visit for register values. We have to |
| 979 // maintain a execution result scope where registers can be allocated. | 948 // maintain a execution result scope where registers can be allocated. |
| 980 ZoneList<CaseClause*>* clauses = stmt->cases(); | 949 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 981 SwitchBuilder switch_builder(builder(), clauses->length()); | 950 SwitchBuilder switch_builder(builder(), clauses->length()); |
| 982 ControlScopeForBreakable scope(this, stmt, &switch_builder); | 951 ControlScopeForBreakable scope(this, stmt, &switch_builder); |
| 983 int default_index = -1; | 952 int default_index = -1; |
| 984 | 953 |
| 985 builder()->SetStatementPosition(stmt); | 954 builder()->SetStatementPosition(stmt); |
| 986 | 955 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1017 for (int i = 0; i < clauses->length(); i++) { | 986 for (int i = 0; i < clauses->length(); i++) { |
| 1018 CaseClause* clause = clauses->at(i); | 987 CaseClause* clause = clauses->at(i); |
| 1019 switch_builder.SetCaseTarget(i); | 988 switch_builder.SetCaseTarget(i); |
| 1020 VisitStatements(clause->statements()); | 989 VisitStatements(clause->statements()); |
| 1021 } | 990 } |
| 1022 builder()->Bind(&done_label); | 991 builder()->Bind(&done_label); |
| 1023 | 992 |
| 1024 switch_builder.SetBreakTarget(done_label); | 993 switch_builder.SetBreakTarget(done_label); |
| 1025 } | 994 } |
| 1026 | 995 |
| 1027 | |
| 1028 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { | 996 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { |
| 1029 // Handled entirely in VisitSwitchStatement. | 997 // Handled entirely in VisitSwitchStatement. |
| 1030 UNREACHABLE(); | 998 UNREACHABLE(); |
| 1031 } | 999 } |
| 1032 | 1000 |
| 1033 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt, | 1001 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt, |
| 1034 LoopBuilder* loop_builder) { | 1002 LoopBuilder* loop_builder) { |
| 1035 ControlScopeForIteration execution_control(this, stmt, loop_builder); | 1003 ControlScopeForIteration execution_control(this, stmt, loop_builder); |
| 1036 builder()->StackCheck(stmt->position()); | 1004 builder()->StackCheck(stmt->position()); |
| 1037 Visit(stmt->body()); | 1005 Visit(stmt->body()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1066 if (!stmt->cond()->ToBooleanIsTrue()) { | 1034 if (!stmt->cond()->ToBooleanIsTrue()) { |
| 1067 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1035 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
| 1068 VisitForAccumulatorValue(stmt->cond()); | 1036 VisitForAccumulatorValue(stmt->cond()); |
| 1069 loop_builder.BreakIfFalse(); | 1037 loop_builder.BreakIfFalse(); |
| 1070 } | 1038 } |
| 1071 VisitIterationBody(stmt, &loop_builder); | 1039 VisitIterationBody(stmt, &loop_builder); |
| 1072 loop_builder.JumpToHeader(); | 1040 loop_builder.JumpToHeader(); |
| 1073 loop_builder.EndLoop(); | 1041 loop_builder.EndLoop(); |
| 1074 } | 1042 } |
| 1075 | 1043 |
| 1076 | |
| 1077 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 1044 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
| 1078 if (stmt->init() != nullptr) { | 1045 if (stmt->init() != nullptr) { |
| 1079 Visit(stmt->init()); | 1046 Visit(stmt->init()); |
| 1080 } | 1047 } |
| 1081 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { | 1048 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) { |
| 1082 // If the condition is known to be false there is no need to generate | 1049 // If the condition is known to be false there is no need to generate |
| 1083 // body, next or condition blocks. Init block should be generated. | 1050 // body, next or condition blocks. Init block should be generated. |
| 1084 return; | 1051 return; |
| 1085 } | 1052 } |
| 1086 | 1053 |
| 1087 LoopBuilder loop_builder(builder()); | 1054 LoopBuilder loop_builder(builder()); |
| 1088 VisitIterationHeader(stmt, &loop_builder); | 1055 VisitIterationHeader(stmt, &loop_builder); |
| 1089 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { | 1056 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { |
| 1090 builder()->SetExpressionAsStatementPosition(stmt->cond()); | 1057 builder()->SetExpressionAsStatementPosition(stmt->cond()); |
| 1091 VisitForAccumulatorValue(stmt->cond()); | 1058 VisitForAccumulatorValue(stmt->cond()); |
| 1092 loop_builder.BreakIfFalse(); | 1059 loop_builder.BreakIfFalse(); |
| 1093 } | 1060 } |
| 1094 VisitIterationBody(stmt, &loop_builder); | 1061 VisitIterationBody(stmt, &loop_builder); |
| 1095 if (stmt->next() != nullptr) { | 1062 if (stmt->next() != nullptr) { |
| 1096 builder()->SetStatementPosition(stmt->next()); | 1063 builder()->SetStatementPosition(stmt->next()); |
| 1097 Visit(stmt->next()); | 1064 Visit(stmt->next()); |
| 1098 } | 1065 } |
| 1099 loop_builder.JumpToHeader(); | 1066 loop_builder.JumpToHeader(); |
| 1100 loop_builder.EndLoop(); | 1067 loop_builder.EndLoop(); |
| 1101 } | 1068 } |
| 1102 | 1069 |
| 1103 | |
| 1104 void BytecodeGenerator::VisitForInAssignment(Expression* expr, | 1070 void BytecodeGenerator::VisitForInAssignment(Expression* expr, |
| 1105 FeedbackVectorSlot slot) { | 1071 FeedbackVectorSlot slot) { |
| 1106 DCHECK(expr->IsValidReferenceExpression()); | 1072 DCHECK(expr->IsValidReferenceExpression()); |
| 1107 | 1073 |
| 1108 // Evaluate assignment starting with the value to be stored in the | 1074 // Evaluate assignment starting with the value to be stored in the |
| 1109 // accumulator. | 1075 // accumulator. |
| 1110 Property* property = expr->AsProperty(); | 1076 Property* property = expr->AsProperty(); |
| 1111 LhsKind assign_type = Property::GetAssignType(property); | 1077 LhsKind assign_type = Property::GetAssignType(property); |
| 1112 switch (assign_type) { | 1078 switch (assign_type) { |
| 1113 case VARIABLE: { | 1079 case VARIABLE: { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1167 property->obj()->AsSuperPropertyReference(); | 1133 property->obj()->AsSuperPropertyReference(); |
| 1168 VisitForRegisterValue(super_property->this_var(), receiver); | 1134 VisitForRegisterValue(super_property->this_var(), receiver); |
| 1169 VisitForRegisterValue(super_property->home_object(), home_object); | 1135 VisitForRegisterValue(super_property->home_object(), home_object); |
| 1170 VisitForRegisterValue(property->key(), key); | 1136 VisitForRegisterValue(property->key(), key); |
| 1171 BuildKeyedSuperPropertyStore(receiver, home_object, key, value); | 1137 BuildKeyedSuperPropertyStore(receiver, home_object, key, value); |
| 1172 break; | 1138 break; |
| 1173 } | 1139 } |
| 1174 } | 1140 } |
| 1175 } | 1141 } |
| 1176 | 1142 |
| 1177 | |
| 1178 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 1143 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
| 1179 if (stmt->subject()->IsNullLiteral() || | 1144 if (stmt->subject()->IsNullLiteral() || |
| 1180 stmt->subject()->IsUndefinedLiteral()) { | 1145 stmt->subject()->IsUndefinedLiteral()) { |
| 1181 // ForIn generates lots of code, skip if it wouldn't produce any effects. | 1146 // ForIn generates lots of code, skip if it wouldn't produce any effects. |
| 1182 return; | 1147 return; |
| 1183 } | 1148 } |
| 1184 | 1149 |
| 1185 LoopBuilder loop_builder(builder()); | 1150 LoopBuilder loop_builder(builder()); |
| 1186 BytecodeLabel subject_null_label, subject_undefined_label; | 1151 BytecodeLabel subject_null_label, subject_undefined_label; |
| 1187 | 1152 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1219 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); | 1184 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); |
| 1220 VisitIterationBody(stmt, &loop_builder); | 1185 VisitIterationBody(stmt, &loop_builder); |
| 1221 builder()->ForInStep(index); | 1186 builder()->ForInStep(index); |
| 1222 builder()->StoreAccumulatorInRegister(index); | 1187 builder()->StoreAccumulatorInRegister(index); |
| 1223 loop_builder.JumpToHeader(); | 1188 loop_builder.JumpToHeader(); |
| 1224 loop_builder.EndLoop(); | 1189 loop_builder.EndLoop(); |
| 1225 builder()->Bind(&subject_null_label); | 1190 builder()->Bind(&subject_null_label); |
| 1226 builder()->Bind(&subject_undefined_label); | 1191 builder()->Bind(&subject_undefined_label); |
| 1227 } | 1192 } |
| 1228 | 1193 |
| 1229 | |
| 1230 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 1194 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
| 1231 LoopBuilder loop_builder(builder()); | 1195 LoopBuilder loop_builder(builder()); |
| 1232 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | 1196 ControlScopeForIteration control_scope(this, stmt, &loop_builder); |
| 1233 | 1197 |
| 1234 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator()); | 1198 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator()); |
| 1235 VisitForEffect(stmt->assign_iterator()); | 1199 VisitForEffect(stmt->assign_iterator()); |
| 1236 | 1200 |
| 1237 VisitIterationHeader(stmt, &loop_builder); | 1201 VisitIterationHeader(stmt, &loop_builder); |
| 1238 builder()->SetExpressionAsStatementPosition(stmt->next_result()); | 1202 builder()->SetExpressionAsStatementPosition(stmt->next_result()); |
| 1239 VisitForEffect(stmt->next_result()); | 1203 VisitForEffect(stmt->next_result()); |
| 1240 VisitForAccumulatorValue(stmt->result_done()); | 1204 VisitForAccumulatorValue(stmt->result_done()); |
| 1241 loop_builder.BreakIfTrue(); | 1205 loop_builder.BreakIfTrue(); |
| 1242 | 1206 |
| 1243 VisitForEffect(stmt->assign_each()); | 1207 VisitForEffect(stmt->assign_each()); |
| 1244 VisitIterationBody(stmt, &loop_builder); | 1208 VisitIterationBody(stmt, &loop_builder); |
| 1245 loop_builder.JumpToHeader(); | 1209 loop_builder.JumpToHeader(); |
| 1246 loop_builder.EndLoop(); | 1210 loop_builder.EndLoop(); |
| 1247 } | 1211 } |
| 1248 | 1212 |
| 1249 | |
| 1250 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 1213 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 1251 TryCatchBuilder try_control_builder(builder()); | 1214 TryCatchBuilder try_control_builder(builder()); |
| 1252 Register no_reg; | 1215 Register no_reg; |
| 1253 | 1216 |
| 1254 // Preserve the context in a dedicated register, so that it can be restored | 1217 // Preserve the context in a dedicated register, so that it can be restored |
| 1255 // when the handler is entered by the stack-unwinding machinery. | 1218 // when the handler is entered by the stack-unwinding machinery. |
| 1256 // TODO(mstarzinger): Be smarter about register allocation. | 1219 // TODO(mstarzinger): Be smarter about register allocation. |
| 1257 Register context = register_allocator()->NewRegister(); | 1220 Register context = register_allocator()->NewRegister(); |
| 1258 builder()->MoveRegister(Register::current_context(), context); | 1221 builder()->MoveRegister(Register::current_context(), context); |
| 1259 | 1222 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1276 } | 1239 } |
| 1277 | 1240 |
| 1278 // Load the catch context into the accumulator. | 1241 // Load the catch context into the accumulator. |
| 1279 builder()->LoadAccumulatorWithRegister(context); | 1242 builder()->LoadAccumulatorWithRegister(context); |
| 1280 | 1243 |
| 1281 // Evaluate the catch-block. | 1244 // Evaluate the catch-block. |
| 1282 VisitInScope(stmt->catch_block(), stmt->scope()); | 1245 VisitInScope(stmt->catch_block(), stmt->scope()); |
| 1283 try_control_builder.EndCatch(); | 1246 try_control_builder.EndCatch(); |
| 1284 } | 1247 } |
| 1285 | 1248 |
| 1286 | |
| 1287 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1249 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
| 1288 TryFinallyBuilder try_control_builder(builder(), IsInsideTryCatch()); | 1250 TryFinallyBuilder try_control_builder(builder(), IsInsideTryCatch()); |
| 1289 Register no_reg; | 1251 Register no_reg; |
| 1290 | 1252 |
| 1291 // We keep a record of all paths that enter the finally-block to be able to | 1253 // We keep a record of all paths that enter the finally-block to be able to |
| 1292 // dispatch to the correct continuation point after the statements in the | 1254 // dispatch to the correct continuation point after the statements in the |
| 1293 // finally-block have been evaluated. | 1255 // finally-block have been evaluated. |
| 1294 // | 1256 // |
| 1295 // The try-finally construct can enter the finally-block in three ways: | 1257 // The try-finally construct can enter the finally-block in three ways: |
| 1296 // 1. By exiting the try-block normally, falling through at the end. | 1258 // 1. By exiting the try-block normally, falling through at the end. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1341 Visit(stmt->finally_block()); | 1303 Visit(stmt->finally_block()); |
| 1342 try_control_builder.EndFinally(); | 1304 try_control_builder.EndFinally(); |
| 1343 | 1305 |
| 1344 // Pending message object is restored on exit. | 1306 // Pending message object is restored on exit. |
| 1345 builder()->CallRuntime(Runtime::kInterpreterSetPendingMessage, message, 1); | 1307 builder()->CallRuntime(Runtime::kInterpreterSetPendingMessage, message, 1); |
| 1346 | 1308 |
| 1347 // Dynamic dispatch after the finally-block. | 1309 // Dynamic dispatch after the finally-block. |
| 1348 commands.ApplyDeferredCommands(); | 1310 commands.ApplyDeferredCommands(); |
| 1349 } | 1311 } |
| 1350 | 1312 |
| 1351 | |
| 1352 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1313 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 1353 builder()->SetStatementPosition(stmt); | 1314 builder()->SetStatementPosition(stmt); |
| 1354 builder()->Debugger(); | 1315 builder()->Debugger(); |
| 1355 } | 1316 } |
| 1356 | 1317 |
| 1357 | |
| 1358 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 1318 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 1359 // Find or build a shared function info. | 1319 // Find or build a shared function info. |
| 1360 Handle<SharedFunctionInfo> shared_info = | 1320 Handle<SharedFunctionInfo> shared_info = |
| 1361 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); | 1321 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); |
| 1362 if (shared_info.is_null()) { | 1322 if (shared_info.is_null()) { |
| 1363 return SetStackOverflow(); | 1323 return SetStackOverflow(); |
| 1364 } | 1324 } |
| 1365 builder()->CreateClosure(shared_info, | 1325 builder()->CreateClosure(shared_info, |
| 1366 expr->pretenure() ? TENURED : NOT_TENURED); | 1326 expr->pretenure() ? TENURED : NOT_TENURED); |
| 1367 execution_result()->SetResultInAccumulator(); | 1327 execution_result()->SetResultInAccumulator(); |
| 1368 } | 1328 } |
| 1369 | 1329 |
| 1370 | |
| 1371 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { | 1330 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { |
| 1372 if (expr->scope()->ContextLocalCount() > 0) { | 1331 if (expr->scope()->ContextLocalCount() > 0) { |
| 1373 VisitNewLocalBlockContext(expr->scope()); | 1332 VisitNewLocalBlockContext(expr->scope()); |
| 1374 ContextScope scope(this, expr->scope()); | 1333 ContextScope scope(this, expr->scope()); |
| 1375 VisitDeclarations(expr->scope()->declarations()); | 1334 VisitDeclarations(expr->scope()->declarations()); |
| 1376 VisitClassLiteralContents(expr); | 1335 VisitClassLiteralContents(expr); |
| 1377 } else { | 1336 } else { |
| 1378 VisitDeclarations(expr->scope()->declarations()); | 1337 VisitDeclarations(expr->scope()->declarations()); |
| 1379 VisitClassLiteralContents(expr); | 1338 VisitClassLiteralContents(expr); |
| 1380 } | 1339 } |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1518 | 1477 |
| 1519 void BytecodeGenerator::VisitNativeFunctionLiteral( | 1478 void BytecodeGenerator::VisitNativeFunctionLiteral( |
| 1520 NativeFunctionLiteral* expr) { | 1479 NativeFunctionLiteral* expr) { |
| 1521 // Find or build a shared function info for the native function template. | 1480 // Find or build a shared function info for the native function template. |
| 1522 Handle<SharedFunctionInfo> shared_info = | 1481 Handle<SharedFunctionInfo> shared_info = |
| 1523 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name()); | 1482 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name()); |
| 1524 builder()->CreateClosure(shared_info, NOT_TENURED); | 1483 builder()->CreateClosure(shared_info, NOT_TENURED); |
| 1525 execution_result()->SetResultInAccumulator(); | 1484 execution_result()->SetResultInAccumulator(); |
| 1526 } | 1485 } |
| 1527 | 1486 |
| 1528 | |
| 1529 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { | 1487 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) { |
| 1530 VisitBlock(expr->block()); | 1488 VisitBlock(expr->block()); |
| 1531 VisitVariableProxy(expr->result()); | 1489 VisitVariableProxy(expr->result()); |
| 1532 } | 1490 } |
| 1533 | 1491 |
| 1534 | |
| 1535 void BytecodeGenerator::VisitConditional(Conditional* expr) { | 1492 void BytecodeGenerator::VisitConditional(Conditional* expr) { |
| 1536 // TODO(rmcilroy): Spot easy cases where there code would not need to | 1493 // TODO(rmcilroy): Spot easy cases where there code would not need to |
| 1537 // emit the then block or the else block, e.g. condition is | 1494 // emit the then block or the else block, e.g. condition is |
| 1538 // obviously true/1/false/0. | 1495 // obviously true/1/false/0. |
| 1539 | 1496 |
| 1540 BytecodeLabel else_label, end_label; | 1497 BytecodeLabel else_label, end_label; |
| 1541 | 1498 |
| 1542 VisitForAccumulatorValue(expr->condition()); | 1499 VisitForAccumulatorValue(expr->condition()); |
| 1543 builder()->JumpIfFalse(&else_label); | 1500 builder()->JumpIfFalse(&else_label); |
| 1544 | 1501 |
| 1545 VisitForAccumulatorValue(expr->then_expression()); | 1502 VisitForAccumulatorValue(expr->then_expression()); |
| 1546 builder()->Jump(&end_label); | 1503 builder()->Jump(&end_label); |
| 1547 | 1504 |
| 1548 builder()->Bind(&else_label); | 1505 builder()->Bind(&else_label); |
| 1549 VisitForAccumulatorValue(expr->else_expression()); | 1506 VisitForAccumulatorValue(expr->else_expression()); |
| 1550 builder()->Bind(&end_label); | 1507 builder()->Bind(&end_label); |
| 1551 | 1508 |
| 1552 execution_result()->SetResultInAccumulator(); | 1509 execution_result()->SetResultInAccumulator(); |
| 1553 } | 1510 } |
| 1554 | 1511 |
| 1555 | |
| 1556 void BytecodeGenerator::VisitLiteral(Literal* expr) { | 1512 void BytecodeGenerator::VisitLiteral(Literal* expr) { |
| 1557 if (!execution_result()->IsEffect()) { | 1513 if (!execution_result()->IsEffect()) { |
| 1558 Handle<Object> value = expr->value(); | 1514 Handle<Object> value = expr->value(); |
| 1559 if (value->IsSmi()) { | 1515 if (value->IsSmi()) { |
| 1560 builder()->LoadLiteral(Smi::cast(*value)); | 1516 builder()->LoadLiteral(Smi::cast(*value)); |
| 1561 } else if (value->IsUndefined()) { | 1517 } else if (value->IsUndefined()) { |
| 1562 builder()->LoadUndefined(); | 1518 builder()->LoadUndefined(); |
| 1563 } else if (value->IsTrue()) { | 1519 } else if (value->IsTrue()) { |
| 1564 builder()->LoadTrue(); | 1520 builder()->LoadTrue(); |
| 1565 } else if (value->IsFalse()) { | 1521 } else if (value->IsFalse()) { |
| 1566 builder()->LoadFalse(); | 1522 builder()->LoadFalse(); |
| 1567 } else if (value->IsNull()) { | 1523 } else if (value->IsNull()) { |
| 1568 builder()->LoadNull(); | 1524 builder()->LoadNull(); |
| 1569 } else if (value->IsTheHole()) { | 1525 } else if (value->IsTheHole()) { |
| 1570 builder()->LoadTheHole(); | 1526 builder()->LoadTheHole(); |
| 1571 } else { | 1527 } else { |
| 1572 builder()->LoadLiteral(value); | 1528 builder()->LoadLiteral(value); |
| 1573 } | 1529 } |
| 1574 execution_result()->SetResultInAccumulator(); | 1530 execution_result()->SetResultInAccumulator(); |
| 1575 } | 1531 } |
| 1576 } | 1532 } |
| 1577 | 1533 |
| 1578 | |
| 1579 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 1534 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 1580 // Materialize a regular expression literal. | 1535 // Materialize a regular expression literal. |
| 1581 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(), | 1536 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(), |
| 1582 expr->flags()); | 1537 expr->flags()); |
| 1583 execution_result()->SetResultInAccumulator(); | 1538 execution_result()->SetResultInAccumulator(); |
| 1584 } | 1539 } |
| 1585 | 1540 |
| 1586 | |
| 1587 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 1541 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
| 1588 // Copy the literal boilerplate. | 1542 // Copy the literal boilerplate. |
| 1589 int fast_clone_properties_count = 0; | 1543 int fast_clone_properties_count = 0; |
| 1590 if (FastCloneShallowObjectStub::IsSupported(expr)) { | 1544 if (FastCloneShallowObjectStub::IsSupported(expr)) { |
| 1591 STATIC_ASSERT( | 1545 STATIC_ASSERT( |
| 1592 FastCloneShallowObjectStub::kMaximumClonedProperties <= | 1546 FastCloneShallowObjectStub::kMaximumClonedProperties <= |
| 1593 1 << CreateObjectLiteralFlags::FastClonePropertiesCountBits::kShift); | 1547 1 << CreateObjectLiteralFlags::FastClonePropertiesCountBits::kShift); |
| 1594 fast_clone_properties_count = | 1548 fast_clone_properties_count = |
| 1595 FastCloneShallowObjectStub::PropertiesCount(expr->properties_count()); | 1549 FastCloneShallowObjectStub::PropertiesCount(expr->properties_count()); |
| 1596 } | 1550 } |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1780 case ObjectLiteral::Property::SETTER: | 1734 case ObjectLiteral::Property::SETTER: |
| 1781 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked, | 1735 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked, |
| 1782 literal_argument, 4); | 1736 literal_argument, 4); |
| 1783 break; | 1737 break; |
| 1784 } | 1738 } |
| 1785 } | 1739 } |
| 1786 | 1740 |
| 1787 execution_result()->SetResultInRegister(literal); | 1741 execution_result()->SetResultInRegister(literal); |
| 1788 } | 1742 } |
| 1789 | 1743 |
| 1790 | |
| 1791 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 1744 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
| 1792 // Deep-copy the literal boilerplate. | 1745 // Deep-copy the literal boilerplate. |
| 1793 builder()->CreateArrayLiteral(expr->constant_elements(), | 1746 builder()->CreateArrayLiteral(expr->constant_elements(), |
| 1794 expr->literal_index(), | 1747 expr->literal_index(), |
| 1795 expr->ComputeFlags(true)); | 1748 expr->ComputeFlags(true)); |
| 1796 Register index, literal; | 1749 Register index, literal; |
| 1797 | 1750 |
| 1798 // Evaluate all the non-constant subexpressions and store them into the | 1751 // Evaluate all the non-constant subexpressions and store them into the |
| 1799 // newly cloned array. | 1752 // newly cloned array. |
| 1800 bool literal_in_accumulator = true; | 1753 bool literal_in_accumulator = true; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1820 language_mode()); | 1773 language_mode()); |
| 1821 } | 1774 } |
| 1822 | 1775 |
| 1823 if (!literal_in_accumulator) { | 1776 if (!literal_in_accumulator) { |
| 1824 // Restore literal array into accumulator. | 1777 // Restore literal array into accumulator. |
| 1825 builder()->LoadAccumulatorWithRegister(literal); | 1778 builder()->LoadAccumulatorWithRegister(literal); |
| 1826 } | 1779 } |
| 1827 execution_result()->SetResultInAccumulator(); | 1780 execution_result()->SetResultInAccumulator(); |
| 1828 } | 1781 } |
| 1829 | 1782 |
| 1830 | |
| 1831 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 1783 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
| 1832 builder()->SetExpressionPosition(proxy); | 1784 builder()->SetExpressionPosition(proxy); |
| 1833 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1785 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
| 1834 } | 1786 } |
| 1835 | 1787 |
| 1836 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode, | 1788 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode, |
| 1837 Handle<String> name) { | 1789 Handle<String> name) { |
| 1838 if (mode == LET || mode == CONST) { | 1790 if (mode == LET || mode == CONST) { |
| 1839 BuildThrowIfHole(name); | 1791 BuildThrowIfHole(name); |
| 1840 } | 1792 } |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2122 break; | 2074 break; |
| 2123 } | 2075 } |
| 2124 case VariableLocation::LOOKUP: { | 2076 case VariableLocation::LOOKUP: { |
| 2125 DCHECK_NE(CONST_LEGACY, variable->mode()); | 2077 DCHECK_NE(CONST_LEGACY, variable->mode()); |
| 2126 builder()->StoreLookupSlot(variable->name(), language_mode()); | 2078 builder()->StoreLookupSlot(variable->name(), language_mode()); |
| 2127 break; | 2079 break; |
| 2128 } | 2080 } |
| 2129 } | 2081 } |
| 2130 } | 2082 } |
| 2131 | 2083 |
| 2132 | |
| 2133 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 2084 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
| 2134 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); | 2085 DCHECK(expr->target()->IsValidReferenceExpressionOrThis()); |
| 2135 Register object, key, home_object, value; | 2086 Register object, key, home_object, value; |
| 2136 Handle<String> name; | 2087 Handle<String> name; |
| 2137 | 2088 |
| 2138 // Left-hand side can only be a property, a global or a variable slot. | 2089 // Left-hand side can only be a property, a global or a variable slot. |
| 2139 Property* property = expr->target()->AsProperty(); | 2090 Property* property = expr->target()->AsProperty(); |
| 2140 LhsKind assign_type = Property::GetAssignType(property); | 2091 LhsKind assign_type = Property::GetAssignType(property); |
| 2141 | 2092 |
| 2142 // Evaluate LHS expression. | 2093 // Evaluate LHS expression. |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2350 VisitForAccumulatorValue(expr->exception()); | 2301 VisitForAccumulatorValue(expr->exception()); |
| 2351 builder()->SetExpressionPosition(expr); | 2302 builder()->SetExpressionPosition(expr); |
| 2352 builder()->Throw(); | 2303 builder()->Throw(); |
| 2353 // Throw statements are modeled as expressions instead of statements. These | 2304 // Throw statements are modeled as expressions instead of statements. These |
| 2354 // are converted from assignment statements in Rewriter::ReWrite pass. An | 2305 // are converted from assignment statements in Rewriter::ReWrite pass. An |
| 2355 // assignment statement expects a value in the accumulator. This is a hack to | 2306 // assignment statement expects a value in the accumulator. This is a hack to |
| 2356 // avoid DCHECK fails assert accumulator has been set. | 2307 // avoid DCHECK fails assert accumulator has been set. |
| 2357 execution_result()->SetResultInAccumulator(); | 2308 execution_result()->SetResultInAccumulator(); |
| 2358 } | 2309 } |
| 2359 | 2310 |
| 2360 | |
| 2361 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { | 2311 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { |
| 2362 LhsKind property_kind = Property::GetAssignType(expr); | 2312 LhsKind property_kind = Property::GetAssignType(expr); |
| 2363 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); | 2313 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); |
| 2364 builder()->SetExpressionPosition(expr); | 2314 builder()->SetExpressionPosition(expr); |
| 2365 switch (property_kind) { | 2315 switch (property_kind) { |
| 2366 case VARIABLE: | 2316 case VARIABLE: |
| 2367 UNREACHABLE(); | 2317 UNREACHABLE(); |
| 2368 case NAMED_PROPERTY: { | 2318 case NAMED_PROPERTY: { |
| 2369 builder()->LoadNamedProperty(obj, | 2319 builder()->LoadNamedProperty(obj, |
| 2370 expr->key()->AsLiteral()->AsPropertyName(), | 2320 expr->key()->AsLiteral()->AsPropertyName(), |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2644 | 2594 |
| 2645 builder()->SetExpressionPosition(expr); | 2595 builder()->SetExpressionPosition(expr); |
| 2646 // The accumulator holds new target which is the same as the | 2596 // The accumulator holds new target which is the same as the |
| 2647 // constructor for CallNew. | 2597 // constructor for CallNew. |
| 2648 builder() | 2598 builder() |
| 2649 ->LoadAccumulatorWithRegister(constructor) | 2599 ->LoadAccumulatorWithRegister(constructor) |
| 2650 .New(constructor, first_arg, args->length()); | 2600 .New(constructor, first_arg, args->length()); |
| 2651 execution_result()->SetResultInAccumulator(); | 2601 execution_result()->SetResultInAccumulator(); |
| 2652 } | 2602 } |
| 2653 | 2603 |
| 2654 | |
| 2655 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 2604 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
| 2656 ZoneList<Expression*>* args = expr->arguments(); | 2605 ZoneList<Expression*>* args = expr->arguments(); |
| 2657 if (expr->is_jsruntime()) { | 2606 if (expr->is_jsruntime()) { |
| 2658 // Allocate a register for the receiver and load it with undefined. | 2607 // Allocate a register for the receiver and load it with undefined. |
| 2659 register_allocator()->PrepareForConsecutiveAllocations(1 + args->length()); | 2608 register_allocator()->PrepareForConsecutiveAllocations(1 + args->length()); |
| 2660 Register receiver = register_allocator()->NextConsecutiveRegister(); | 2609 Register receiver = register_allocator()->NextConsecutiveRegister(); |
| 2661 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 2610 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
| 2662 Register first_arg = VisitArguments(args); | 2611 Register first_arg = VisitArguments(args); |
| 2663 CHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1); | 2612 CHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1); |
| 2664 builder()->CallJSRuntime(expr->context_index(), receiver, | 2613 builder()->CallJSRuntime(expr->context_index(), receiver, |
| 2665 1 + args->length()); | 2614 1 + args->length()); |
| 2666 } else { | 2615 } else { |
| 2667 // Evaluate all arguments to the runtime call. | 2616 // Evaluate all arguments to the runtime call. |
| 2668 Register first_arg = VisitArguments(args); | 2617 Register first_arg = VisitArguments(args); |
| 2669 Runtime::FunctionId function_id = expr->function()->function_id; | 2618 Runtime::FunctionId function_id = expr->function()->function_id; |
| 2670 builder()->CallRuntime(function_id, first_arg, args->length()); | 2619 builder()->CallRuntime(function_id, first_arg, args->length()); |
| 2671 } | 2620 } |
| 2672 execution_result()->SetResultInAccumulator(); | 2621 execution_result()->SetResultInAccumulator(); |
| 2673 } | 2622 } |
| 2674 | 2623 |
| 2675 | |
| 2676 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { | 2624 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { |
| 2677 VisitForEffect(expr->expression()); | 2625 VisitForEffect(expr->expression()); |
| 2678 builder()->LoadUndefined(); | 2626 builder()->LoadUndefined(); |
| 2679 execution_result()->SetResultInAccumulator(); | 2627 execution_result()->SetResultInAccumulator(); |
| 2680 } | 2628 } |
| 2681 | 2629 |
| 2682 | |
| 2683 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { | 2630 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { |
| 2684 if (expr->expression()->IsVariableProxy()) { | 2631 if (expr->expression()->IsVariableProxy()) { |
| 2685 // Typeof does not throw a reference error on global variables, hence we | 2632 // Typeof does not throw a reference error on global variables, hence we |
| 2686 // perform a non-contextual load in case the operand is a variable proxy. | 2633 // perform a non-contextual load in case the operand is a variable proxy. |
| 2687 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2634 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 2688 VisitVariableLoadForAccumulatorValue( | 2635 VisitVariableLoadForAccumulatorValue( |
| 2689 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF); | 2636 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF); |
| 2690 } else { | 2637 } else { |
| 2691 VisitForAccumulatorValue(expr->expression()); | 2638 VisitForAccumulatorValue(expr->expression()); |
| 2692 } | 2639 } |
| 2693 builder()->TypeOf(); | 2640 builder()->TypeOf(); |
| 2694 execution_result()->SetResultInAccumulator(); | 2641 execution_result()->SetResultInAccumulator(); |
| 2695 } | 2642 } |
| 2696 | 2643 |
| 2697 | |
| 2698 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { | 2644 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { |
| 2699 VisitForAccumulatorValue(expr->expression()); | 2645 VisitForAccumulatorValue(expr->expression()); |
| 2700 builder()->LogicalNot(); | 2646 builder()->LogicalNot(); |
| 2701 execution_result()->SetResultInAccumulator(); | 2647 execution_result()->SetResultInAccumulator(); |
| 2702 } | 2648 } |
| 2703 | 2649 |
| 2704 | |
| 2705 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 2650 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
| 2706 switch (expr->op()) { | 2651 switch (expr->op()) { |
| 2707 case Token::Value::NOT: | 2652 case Token::Value::NOT: |
| 2708 VisitNot(expr); | 2653 VisitNot(expr); |
| 2709 break; | 2654 break; |
| 2710 case Token::Value::TYPEOF: | 2655 case Token::Value::TYPEOF: |
| 2711 VisitTypeOf(expr); | 2656 VisitTypeOf(expr); |
| 2712 break; | 2657 break; |
| 2713 case Token::Value::VOID: | 2658 case Token::Value::VOID: |
| 2714 VisitVoid(expr); | 2659 VisitVoid(expr); |
| 2715 break; | 2660 break; |
| 2716 case Token::Value::DELETE: | 2661 case Token::Value::DELETE: |
| 2717 VisitDelete(expr); | 2662 VisitDelete(expr); |
| 2718 break; | 2663 break; |
| 2719 case Token::Value::BIT_NOT: | 2664 case Token::Value::BIT_NOT: |
| 2720 case Token::Value::ADD: | 2665 case Token::Value::ADD: |
| 2721 case Token::Value::SUB: | 2666 case Token::Value::SUB: |
| 2722 // These operators are converted to an equivalent binary operators in | 2667 // These operators are converted to an equivalent binary operators in |
| 2723 // the parser. These operators are not expected to be visited here. | 2668 // the parser. These operators are not expected to be visited here. |
| 2724 UNREACHABLE(); | 2669 UNREACHABLE(); |
| 2725 default: | 2670 default: |
| 2726 UNREACHABLE(); | 2671 UNREACHABLE(); |
| 2727 } | 2672 } |
| 2728 } | 2673 } |
| 2729 | 2674 |
| 2730 | |
| 2731 void BytecodeGenerator::VisitDelete(UnaryOperation* expr) { | 2675 void BytecodeGenerator::VisitDelete(UnaryOperation* expr) { |
| 2732 if (expr->expression()->IsProperty()) { | 2676 if (expr->expression()->IsProperty()) { |
| 2733 // Delete of an object property is allowed both in sloppy | 2677 // Delete of an object property is allowed both in sloppy |
| 2734 // and strict modes. | 2678 // and strict modes. |
| 2735 Property* property = expr->expression()->AsProperty(); | 2679 Property* property = expr->expression()->AsProperty(); |
| 2736 Register object = VisitForRegisterValue(property->obj()); | 2680 Register object = VisitForRegisterValue(property->obj()); |
| 2737 VisitForAccumulatorValue(property->key()); | 2681 VisitForAccumulatorValue(property->key()); |
| 2738 builder()->Delete(object, language_mode()); | 2682 builder()->Delete(object, language_mode()); |
| 2739 } else if (expr->expression()->IsVariableProxy()) { | 2683 } else if (expr->expression()->IsVariableProxy()) { |
| 2740 // Delete of an unqualified identifier is allowed in sloppy mode but is | 2684 // Delete of an unqualified identifier is allowed in sloppy mode but is |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2782 UNREACHABLE(); | 2726 UNREACHABLE(); |
| 2783 } | 2727 } |
| 2784 } else { | 2728 } else { |
| 2785 // Delete of an unresolvable reference returns true. | 2729 // Delete of an unresolvable reference returns true. |
| 2786 VisitForEffect(expr->expression()); | 2730 VisitForEffect(expr->expression()); |
| 2787 builder()->LoadTrue(); | 2731 builder()->LoadTrue(); |
| 2788 } | 2732 } |
| 2789 execution_result()->SetResultInAccumulator(); | 2733 execution_result()->SetResultInAccumulator(); |
| 2790 } | 2734 } |
| 2791 | 2735 |
| 2792 | |
| 2793 void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { | 2736 void BytecodeGenerator::VisitCountOperation(CountOperation* expr) { |
| 2794 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis()); | 2737 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis()); |
| 2795 | 2738 |
| 2796 // Left-hand side can only be a property, a global or a variable slot. | 2739 // Left-hand side can only be a property, a global or a variable slot. |
| 2797 Property* property = expr->expression()->AsProperty(); | 2740 Property* property = expr->expression()->AsProperty(); |
| 2798 LhsKind assign_type = Property::GetAssignType(property); | 2741 LhsKind assign_type = Property::GetAssignType(property); |
| 2799 | 2742 |
| 2800 // TODO(rmcilroy): Set is_postfix to false if visiting for effect. | 2743 // TODO(rmcilroy): Set is_postfix to false if visiting for effect. |
| 2801 bool is_postfix = expr->is_postfix(); | 2744 bool is_postfix = expr->is_postfix(); |
| 2802 | 2745 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2904 } | 2847 } |
| 2905 | 2848 |
| 2906 // Restore old value for postfix expressions. | 2849 // Restore old value for postfix expressions. |
| 2907 if (is_postfix) { | 2850 if (is_postfix) { |
| 2908 execution_result()->SetResultInRegister(old_value); | 2851 execution_result()->SetResultInRegister(old_value); |
| 2909 } else { | 2852 } else { |
| 2910 execution_result()->SetResultInAccumulator(); | 2853 execution_result()->SetResultInAccumulator(); |
| 2911 } | 2854 } |
| 2912 } | 2855 } |
| 2913 | 2856 |
| 2914 | |
| 2915 void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) { | 2857 void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) { |
| 2916 switch (binop->op()) { | 2858 switch (binop->op()) { |
| 2917 case Token::COMMA: | 2859 case Token::COMMA: |
| 2918 VisitCommaExpression(binop); | 2860 VisitCommaExpression(binop); |
| 2919 break; | 2861 break; |
| 2920 case Token::OR: | 2862 case Token::OR: |
| 2921 VisitLogicalOrExpression(binop); | 2863 VisitLogicalOrExpression(binop); |
| 2922 break; | 2864 break; |
| 2923 case Token::AND: | 2865 case Token::AND: |
| 2924 VisitLogicalAndExpression(binop); | 2866 VisitLogicalAndExpression(binop); |
| 2925 break; | 2867 break; |
| 2926 default: | 2868 default: |
| 2927 VisitArithmeticExpression(binop); | 2869 VisitArithmeticExpression(binop); |
| 2928 break; | 2870 break; |
| 2929 } | 2871 } |
| 2930 } | 2872 } |
| 2931 | 2873 |
| 2932 | |
| 2933 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 2874 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 2934 Register lhs = VisitForRegisterValue(expr->left()); | 2875 Register lhs = VisitForRegisterValue(expr->left()); |
| 2935 VisitForAccumulatorValue(expr->right()); | 2876 VisitForAccumulatorValue(expr->right()); |
| 2936 builder()->SetExpressionPosition(expr); | 2877 builder()->SetExpressionPosition(expr); |
| 2937 builder()->CompareOperation(expr->op(), lhs); | 2878 builder()->CompareOperation(expr->op(), lhs); |
| 2938 execution_result()->SetResultInAccumulator(); | 2879 execution_result()->SetResultInAccumulator(); |
| 2939 } | 2880 } |
| 2940 | 2881 |
| 2941 | |
| 2942 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { | 2882 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { |
| 2943 Register lhs = VisitForRegisterValue(expr->left()); | 2883 Register lhs = VisitForRegisterValue(expr->left()); |
| 2944 VisitForAccumulatorValue(expr->right()); | 2884 VisitForAccumulatorValue(expr->right()); |
| 2945 builder()->BinaryOperation(expr->op(), lhs); | 2885 builder()->BinaryOperation(expr->op(), lhs); |
| 2946 execution_result()->SetResultInAccumulator(); | 2886 execution_result()->SetResultInAccumulator(); |
| 2947 } | 2887 } |
| 2948 | 2888 |
| 2949 | |
| 2950 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } | 2889 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } |
| 2951 | 2890 |
| 2952 | |
| 2953 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { | 2891 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { |
| 2954 UNREACHABLE(); | 2892 UNREACHABLE(); |
| 2955 } | 2893 } |
| 2956 | 2894 |
| 2957 | |
| 2958 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { | 2895 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 2959 execution_result()->SetResultInRegister(Register::function_closure()); | 2896 execution_result()->SetResultInRegister(Register::function_closure()); |
| 2960 } | 2897 } |
| 2961 | 2898 |
| 2962 | |
| 2963 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { | 2899 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) { |
| 2964 // Handled by VisitCall(). | 2900 // Handled by VisitCall(). |
| 2965 UNREACHABLE(); | 2901 UNREACHABLE(); |
| 2966 } | 2902 } |
| 2967 | 2903 |
| 2968 | |
| 2969 void BytecodeGenerator::VisitSuperPropertyReference( | 2904 void BytecodeGenerator::VisitSuperPropertyReference( |
| 2970 SuperPropertyReference* expr) { | 2905 SuperPropertyReference* expr) { |
| 2971 builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError, Register(0), 0); | 2906 builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError, Register(0), 0); |
| 2972 execution_result()->SetResultInAccumulator(); | 2907 execution_result()->SetResultInAccumulator(); |
| 2973 } | 2908 } |
| 2974 | 2909 |
| 2975 | |
| 2976 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { | 2910 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { |
| 2977 VisitForEffect(binop->left()); | 2911 VisitForEffect(binop->left()); |
| 2978 Visit(binop->right()); | 2912 Visit(binop->right()); |
| 2979 } | 2913 } |
| 2980 | 2914 |
| 2981 | |
| 2982 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { | 2915 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { |
| 2983 Expression* left = binop->left(); | 2916 Expression* left = binop->left(); |
| 2984 Expression* right = binop->right(); | 2917 Expression* right = binop->right(); |
| 2985 | 2918 |
| 2986 // Short-circuit evaluation- If it is known that left is always true, | 2919 // Short-circuit evaluation- If it is known that left is always true, |
| 2987 // no need to visit right | 2920 // no need to visit right |
| 2988 if (left->ToBooleanIsTrue()) { | 2921 if (left->ToBooleanIsTrue()) { |
| 2989 VisitForAccumulatorValue(left); | 2922 VisitForAccumulatorValue(left); |
| 2990 } else { | 2923 } else { |
| 2991 BytecodeLabel end_label; | 2924 BytecodeLabel end_label; |
| 2992 VisitForAccumulatorValue(left); | 2925 VisitForAccumulatorValue(left); |
| 2993 builder()->JumpIfTrue(&end_label); | 2926 builder()->JumpIfTrue(&end_label); |
| 2994 VisitForAccumulatorValue(right); | 2927 VisitForAccumulatorValue(right); |
| 2995 builder()->Bind(&end_label); | 2928 builder()->Bind(&end_label); |
| 2996 } | 2929 } |
| 2997 execution_result()->SetResultInAccumulator(); | 2930 execution_result()->SetResultInAccumulator(); |
| 2998 } | 2931 } |
| 2999 | 2932 |
| 3000 | |
| 3001 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { | 2933 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { |
| 3002 Expression* left = binop->left(); | 2934 Expression* left = binop->left(); |
| 3003 Expression* right = binop->right(); | 2935 Expression* right = binop->right(); |
| 3004 | 2936 |
| 3005 // Short-circuit evaluation- If it is known that left is always false, | 2937 // Short-circuit evaluation- If it is known that left is always false, |
| 3006 // no need to visit right | 2938 // no need to visit right |
| 3007 if (left->ToBooleanIsFalse()) { | 2939 if (left->ToBooleanIsFalse()) { |
| 3008 VisitForAccumulatorValue(left); | 2940 VisitForAccumulatorValue(left); |
| 3009 } else { | 2941 } else { |
| 3010 BytecodeLabel end_label; | 2942 BytecodeLabel end_label; |
| 3011 VisitForAccumulatorValue(left); | 2943 VisitForAccumulatorValue(left); |
| 3012 builder()->JumpIfFalse(&end_label); | 2944 builder()->JumpIfFalse(&end_label); |
| 3013 VisitForAccumulatorValue(right); | 2945 VisitForAccumulatorValue(right); |
| 3014 builder()->Bind(&end_label); | 2946 builder()->Bind(&end_label); |
| 3015 } | 2947 } |
| 3016 execution_result()->SetResultInAccumulator(); | 2948 execution_result()->SetResultInAccumulator(); |
| 3017 } | 2949 } |
| 3018 | 2950 |
| 3019 | |
| 3020 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { | 2951 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) { |
| 3021 Visit(expr->expression()); | 2952 Visit(expr->expression()); |
| 3022 } | 2953 } |
| 3023 | 2954 |
| 3024 | |
| 3025 void BytecodeGenerator::VisitNewLocalFunctionContext() { | 2955 void BytecodeGenerator::VisitNewLocalFunctionContext() { |
| 3026 AccumulatorResultScope accumulator_execution_result(this); | 2956 AccumulatorResultScope accumulator_execution_result(this); |
| 3027 Scope* scope = this->scope(); | 2957 Scope* scope = this->scope(); |
| 3028 | 2958 |
| 3029 // Allocate a new local context. | 2959 // Allocate a new local context. |
| 3030 if (scope->is_script_scope()) { | 2960 if (scope->is_script_scope()) { |
| 3031 RegisterAllocationScope register_scope(this); | 2961 RegisterAllocationScope register_scope(this); |
| 3032 Register closure = register_allocator()->NewRegister(); | 2962 Register closure = register_allocator()->NewRegister(); |
| 3033 Register scope_info = register_allocator()->NewRegister(); | 2963 Register scope_info = register_allocator()->NewRegister(); |
| 3034 DCHECK(Register::AreContiguous(closure, scope_info)); | 2964 DCHECK(Register::AreContiguous(closure, scope_info)); |
| 3035 builder() | 2965 builder() |
| 3036 ->LoadAccumulatorWithRegister(Register::function_closure()) | 2966 ->LoadAccumulatorWithRegister(Register::function_closure()) |
| 3037 .StoreAccumulatorInRegister(closure) | 2967 .StoreAccumulatorInRegister(closure) |
| 3038 .LoadLiteral(scope->GetScopeInfo(isolate())) | 2968 .LoadLiteral(scope->GetScopeInfo(isolate())) |
| 3039 .StoreAccumulatorInRegister(scope_info) | 2969 .StoreAccumulatorInRegister(scope_info) |
| 3040 .CallRuntime(Runtime::kNewScriptContext, closure, 2); | 2970 .CallRuntime(Runtime::kNewScriptContext, closure, 2); |
| 3041 } else { | 2971 } else { |
| 3042 builder()->CallRuntime(Runtime::kNewFunctionContext, | 2972 builder()->CallRuntime(Runtime::kNewFunctionContext, |
| 3043 Register::function_closure(), 1); | 2973 Register::function_closure(), 1); |
| 3044 } | 2974 } |
| 3045 execution_result()->SetResultInAccumulator(); | 2975 execution_result()->SetResultInAccumulator(); |
| 3046 } | 2976 } |
| 3047 | 2977 |
| 3048 | |
| 3049 void BytecodeGenerator::VisitBuildLocalActivationContext() { | 2978 void BytecodeGenerator::VisitBuildLocalActivationContext() { |
| 3050 Scope* scope = this->scope(); | 2979 Scope* scope = this->scope(); |
| 3051 | 2980 |
| 3052 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | 2981 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { |
| 3053 Variable* variable = scope->receiver(); | 2982 Variable* variable = scope->receiver(); |
| 3054 Register receiver(builder()->Parameter(0)); | 2983 Register receiver(builder()->Parameter(0)); |
| 3055 // Context variable (at bottom of the context chain). | 2984 // Context variable (at bottom of the context chain). |
| 3056 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 2985 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| 3057 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot( | 2986 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot( |
| 3058 execution_context()->reg(), variable->index()); | 2987 execution_context()->reg(), variable->index()); |
| 3059 } | 2988 } |
| 3060 | 2989 |
| 3061 // Copy parameters into context if necessary. | 2990 // Copy parameters into context if necessary. |
| 3062 int num_parameters = scope->num_parameters(); | 2991 int num_parameters = scope->num_parameters(); |
| 3063 for (int i = 0; i < num_parameters; i++) { | 2992 for (int i = 0; i < num_parameters; i++) { |
| 3064 Variable* variable = scope->parameter(i); | 2993 Variable* variable = scope->parameter(i); |
| 3065 if (!variable->IsContextSlot()) continue; | 2994 if (!variable->IsContextSlot()) continue; |
| 3066 | 2995 |
| 3067 // The parameter indices are shifted by 1 (receiver is variable | 2996 // The parameter indices are shifted by 1 (receiver is variable |
| 3068 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 2997 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
| 3069 Register parameter(builder()->Parameter(i + 1)); | 2998 Register parameter(builder()->Parameter(i + 1)); |
| 3070 // Context variable (at bottom of the context chain). | 2999 // Context variable (at bottom of the context chain). |
| 3071 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | 3000 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); |
| 3072 builder()->LoadAccumulatorWithRegister(parameter) | 3001 builder()->LoadAccumulatorWithRegister(parameter) |
| 3073 .StoreContextSlot(execution_context()->reg(), variable->index()); | 3002 .StoreContextSlot(execution_context()->reg(), variable->index()); |
| 3074 } | 3003 } |
| 3075 } | 3004 } |
| 3076 | 3005 |
| 3077 | |
| 3078 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) { | 3006 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) { |
| 3079 AccumulatorResultScope accumulator_execution_result(this); | 3007 AccumulatorResultScope accumulator_execution_result(this); |
| 3080 DCHECK(scope->is_block_scope()); | 3008 DCHECK(scope->is_block_scope()); |
| 3081 | 3009 |
| 3082 // Allocate a new local block context. | 3010 // Allocate a new local block context. |
| 3083 register_allocator()->PrepareForConsecutiveAllocations(2); | 3011 register_allocator()->PrepareForConsecutiveAllocations(2); |
| 3084 Register scope_info = register_allocator()->NextConsecutiveRegister(); | 3012 Register scope_info = register_allocator()->NextConsecutiveRegister(); |
| 3085 Register closure = register_allocator()->NextConsecutiveRegister(); | 3013 Register closure = register_allocator()->NextConsecutiveRegister(); |
| 3086 | 3014 |
| 3087 builder() | 3015 builder() |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3121 builder() | 3049 builder() |
| 3122 ->StoreAccumulatorInRegister(exception) | 3050 ->StoreAccumulatorInRegister(exception) |
| 3123 .LoadLiteral(variable->name()) | 3051 .LoadLiteral(variable->name()) |
| 3124 .StoreAccumulatorInRegister(name); | 3052 .StoreAccumulatorInRegister(name); |
| 3125 VisitFunctionClosureForContext(); | 3053 VisitFunctionClosureForContext(); |
| 3126 builder()->StoreAccumulatorInRegister(closure).CallRuntime( | 3054 builder()->StoreAccumulatorInRegister(closure).CallRuntime( |
| 3127 Runtime::kPushCatchContext, name, 3); | 3055 Runtime::kPushCatchContext, name, 3); |
| 3128 execution_result()->SetResultInAccumulator(); | 3056 execution_result()->SetResultInAccumulator(); |
| 3129 } | 3057 } |
| 3130 | 3058 |
| 3131 | |
| 3132 void BytecodeGenerator::VisitObjectLiteralAccessor( | 3059 void BytecodeGenerator::VisitObjectLiteralAccessor( |
| 3133 Register home_object, ObjectLiteralProperty* property, Register value_out) { | 3060 Register home_object, ObjectLiteralProperty* property, Register value_out) { |
| 3134 // TODO(rmcilroy): Replace value_out with VisitForRegister(); | 3061 // TODO(rmcilroy): Replace value_out with VisitForRegister(); |
| 3135 if (property == nullptr) { | 3062 if (property == nullptr) { |
| 3136 builder()->LoadNull().StoreAccumulatorInRegister(value_out); | 3063 builder()->LoadNull().StoreAccumulatorInRegister(value_out); |
| 3137 } else { | 3064 } else { |
| 3138 VisitForAccumulatorValue(property->value()); | 3065 VisitForAccumulatorValue(property->value()); |
| 3139 builder()->StoreAccumulatorInRegister(value_out); | 3066 builder()->StoreAccumulatorInRegister(value_out); |
| 3140 VisitSetHomeObject(value_out, home_object, property); | 3067 VisitSetHomeObject(value_out, home_object, property); |
| 3141 } | 3068 } |
| 3142 } | 3069 } |
| 3143 | 3070 |
| 3144 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, | 3071 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, |
| 3145 ObjectLiteralProperty* property, | 3072 ObjectLiteralProperty* property, |
| 3146 int slot_number) { | 3073 int slot_number) { |
| 3147 Expression* expr = property->value(); | 3074 Expression* expr = property->value(); |
| 3148 if (FunctionLiteral::NeedsHomeObject(expr)) { | 3075 if (FunctionLiteral::NeedsHomeObject(expr)) { |
| 3149 Handle<Name> name = isolate()->factory()->home_object_symbol(); | 3076 Handle<Name> name = isolate()->factory()->home_object_symbol(); |
| 3150 FeedbackVectorSlot slot = property->GetSlot(slot_number); | 3077 FeedbackVectorSlot slot = property->GetSlot(slot_number); |
| 3151 builder() | 3078 builder() |
| 3152 ->LoadAccumulatorWithRegister(home_object) | 3079 ->LoadAccumulatorWithRegister(home_object) |
| 3153 .StoreNamedProperty(value, name, feedback_index(slot), language_mode()); | 3080 .StoreNamedProperty(value, name, feedback_index(slot), language_mode()); |
| 3154 } | 3081 } |
| 3155 } | 3082 } |
| 3156 | 3083 |
| 3157 | |
| 3158 void BytecodeGenerator::VisitArgumentsObject(Variable* variable) { | 3084 void BytecodeGenerator::VisitArgumentsObject(Variable* variable) { |
| 3159 if (variable == nullptr) return; | 3085 if (variable == nullptr) return; |
| 3160 | 3086 |
| 3161 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); | 3087 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated()); |
| 3162 | 3088 |
| 3163 // Allocate and initialize a new arguments object and assign to the | 3089 // Allocate and initialize a new arguments object and assign to the |
| 3164 // {arguments} variable. | 3090 // {arguments} variable. |
| 3165 CreateArgumentsType type = | 3091 CreateArgumentsType type = |
| 3166 is_strict(language_mode()) || !info()->has_simple_parameters() | 3092 is_strict(language_mode()) || !info()->has_simple_parameters() |
| 3167 ? CreateArgumentsType::kUnmappedArguments | 3093 ? CreateArgumentsType::kUnmappedArguments |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3182 } | 3108 } |
| 3183 | 3109 |
| 3184 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { | 3110 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) { |
| 3185 if (variable == nullptr) return; | 3111 if (variable == nullptr) return; |
| 3186 | 3112 |
| 3187 // Store the closure we were called with in the given variable. | 3113 // Store the closure we were called with in the given variable. |
| 3188 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 3114 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 3189 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); | 3115 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
| 3190 } | 3116 } |
| 3191 | 3117 |
| 3192 | |
| 3193 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { | 3118 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) { |
| 3194 if (variable == nullptr) return; | 3119 if (variable == nullptr) return; |
| 3195 | 3120 |
| 3196 // Store the new target we were called with in the given variable. | 3121 // Store the new target we were called with in the given variable. |
| 3197 builder()->LoadAccumulatorWithRegister(Register::new_target()); | 3122 builder()->LoadAccumulatorWithRegister(Register::new_target()); |
| 3198 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); | 3123 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid()); |
| 3199 } | 3124 } |
| 3200 | 3125 |
| 3201 | |
| 3202 void BytecodeGenerator::VisitFunctionClosureForContext() { | 3126 void BytecodeGenerator::VisitFunctionClosureForContext() { |
| 3203 AccumulatorResultScope accumulator_execution_result(this); | 3127 AccumulatorResultScope accumulator_execution_result(this); |
| 3204 Scope* closure_scope = execution_context()->scope()->ClosureScope(); | 3128 Scope* closure_scope = execution_context()->scope()->ClosureScope(); |
| 3205 if (closure_scope->is_script_scope() || | 3129 if (closure_scope->is_script_scope() || |
| 3206 closure_scope->is_module_scope()) { | 3130 closure_scope->is_module_scope()) { |
| 3207 // Contexts nested in the native context have a canonical empty function as | 3131 // Contexts nested in the native context have a canonical empty function as |
| 3208 // their closure, not the anonymous closure containing the global code. | 3132 // their closure, not the anonymous closure containing the global code. |
| 3209 Register native_context = register_allocator()->NewRegister(); | 3133 Register native_context = register_allocator()->NewRegister(); |
| 3210 builder() | 3134 builder() |
| 3211 ->LoadContextSlot(execution_context()->reg(), | 3135 ->LoadContextSlot(execution_context()->reg(), |
| 3212 Context::NATIVE_CONTEXT_INDEX) | 3136 Context::NATIVE_CONTEXT_INDEX) |
| 3213 .StoreAccumulatorInRegister(native_context) | 3137 .StoreAccumulatorInRegister(native_context) |
| 3214 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); | 3138 .LoadContextSlot(native_context, Context::CLOSURE_INDEX); |
| 3215 } else if (closure_scope->is_eval_scope()) { | 3139 } else if (closure_scope->is_eval_scope()) { |
| 3216 // Contexts created by a call to eval have the same closure as the | 3140 // Contexts created by a call to eval have the same closure as the |
| 3217 // context calling eval, not the anonymous closure containing the eval | 3141 // context calling eval, not the anonymous closure containing the eval |
| 3218 // code. Fetch it from the context. | 3142 // code. Fetch it from the context. |
| 3219 builder()->LoadContextSlot(execution_context()->reg(), | 3143 builder()->LoadContextSlot(execution_context()->reg(), |
| 3220 Context::CLOSURE_INDEX); | 3144 Context::CLOSURE_INDEX); |
| 3221 } else { | 3145 } else { |
| 3222 DCHECK(closure_scope->is_function_scope()); | 3146 DCHECK(closure_scope->is_function_scope()); |
| 3223 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | 3147 builder()->LoadAccumulatorWithRegister(Register::function_closure()); |
| 3224 } | 3148 } |
| 3225 execution_result()->SetResultInAccumulator(); | 3149 execution_result()->SetResultInAccumulator(); |
| 3226 } | 3150 } |
| 3227 | 3151 |
| 3228 | |
| 3229 // Visits the expression |expr| and places the result in the accumulator. | 3152 // Visits the expression |expr| and places the result in the accumulator. |
| 3230 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | 3153 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { |
| 3231 AccumulatorResultScope accumulator_scope(this); | 3154 AccumulatorResultScope accumulator_scope(this); |
| 3232 Visit(expr); | 3155 Visit(expr); |
| 3233 } | 3156 } |
| 3234 | 3157 |
| 3235 void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) { | 3158 void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) { |
| 3236 if (expr == nullptr) { | 3159 if (expr == nullptr) { |
| 3237 builder()->LoadTheHole(); | 3160 builder()->LoadTheHole(); |
| 3238 } else { | 3161 } else { |
| 3239 VisitForAccumulatorValue(expr); | 3162 VisitForAccumulatorValue(expr); |
| 3240 } | 3163 } |
| 3241 } | 3164 } |
| 3242 | 3165 |
| 3243 // Visits the expression |expr| and discards the result. | 3166 // Visits the expression |expr| and discards the result. |
| 3244 void BytecodeGenerator::VisitForEffect(Expression* expr) { | 3167 void BytecodeGenerator::VisitForEffect(Expression* expr) { |
| 3245 EffectResultScope effect_scope(this); | 3168 EffectResultScope effect_scope(this); |
| 3246 Visit(expr); | 3169 Visit(expr); |
| 3247 } | 3170 } |
| 3248 | 3171 |
| 3249 | |
| 3250 // Visits the expression |expr| and returns the register containing | 3172 // Visits the expression |expr| and returns the register containing |
| 3251 // the expression result. | 3173 // the expression result. |
| 3252 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { | 3174 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { |
| 3253 RegisterResultScope register_scope(this); | 3175 RegisterResultScope register_scope(this); |
| 3254 Visit(expr); | 3176 Visit(expr); |
| 3255 return register_scope.ResultRegister(); | 3177 return register_scope.ResultRegister(); |
| 3256 } | 3178 } |
| 3257 | 3179 |
| 3258 // Visits the expression |expr| and stores the expression result in | 3180 // Visits the expression |expr| and stores the expression result in |
| 3259 // |destination|. | 3181 // |destination|. |
| 3260 void BytecodeGenerator::VisitForRegisterValue(Expression* expr, | 3182 void BytecodeGenerator::VisitForRegisterValue(Expression* expr, |
| 3261 Register destination) { | 3183 Register destination) { |
| 3262 AccumulatorResultScope register_scope(this); | 3184 AccumulatorResultScope register_scope(this); |
| 3263 Visit(expr); | 3185 Visit(expr); |
| 3264 builder()->StoreAccumulatorInRegister(destination); | 3186 builder()->StoreAccumulatorInRegister(destination); |
| 3265 } | 3187 } |
| 3266 | 3188 |
| 3267 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { | 3189 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) { |
| 3268 ContextScope context_scope(this, scope); | 3190 ContextScope context_scope(this, scope); |
| 3269 DCHECK(scope->declarations()->is_empty()); | 3191 DCHECK(scope->declarations()->is_empty()); |
| 3270 Visit(stmt); | 3192 Visit(stmt); |
| 3271 } | 3193 } |
| 3272 | 3194 |
| 3273 | |
| 3274 LanguageMode BytecodeGenerator::language_mode() const { | 3195 LanguageMode BytecodeGenerator::language_mode() const { |
| 3275 return execution_context()->scope()->language_mode(); | 3196 return execution_context()->scope()->language_mode(); |
| 3276 } | 3197 } |
| 3277 | 3198 |
| 3278 | |
| 3279 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 3199 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
| 3280 return TypeFeedbackVector::GetIndex(slot); | 3200 return TypeFeedbackVector::GetIndex(slot); |
| 3281 } | 3201 } |
| 3282 | 3202 |
| 3283 } // namespace interpreter | 3203 } // namespace interpreter |
| 3284 } // namespace internal | 3204 } // namespace internal |
| 3285 } // namespace v8 | 3205 } // namespace v8 |
| OLD | NEW |