| 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/compile-time-value.h" | 7 #include "src/ast/compile-time-value.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/builtins/builtins-constructor.h" | 9 #include "src/builtins/builtins-constructor.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 explicit ControlScope(BytecodeGenerator* generator) | 99 explicit ControlScope(BytecodeGenerator* generator) |
| 100 : generator_(generator), outer_(generator->execution_control()), | 100 : generator_(generator), outer_(generator->execution_control()), |
| 101 context_(generator->execution_context()) { | 101 context_(generator->execution_context()) { |
| 102 generator_->set_execution_control(this); | 102 generator_->set_execution_control(this); |
| 103 } | 103 } |
| 104 virtual ~ControlScope() { generator_->set_execution_control(outer()); } | 104 virtual ~ControlScope() { generator_->set_execution_control(outer()); } |
| 105 | 105 |
| 106 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); } | 106 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); } |
| 107 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); } | 107 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); } |
| 108 void ReturnAccumulator() { PerformCommand(CMD_RETURN, nullptr); } | 108 void ReturnAccumulator() { PerformCommand(CMD_RETURN, nullptr); } |
| 109 void AsyncReturnAccumulator() { PerformCommand(CMD_ASYNC_RETURN, nullptr); } |
| 109 void ReThrowAccumulator() { PerformCommand(CMD_RETHROW, nullptr); } | 110 void ReThrowAccumulator() { PerformCommand(CMD_RETHROW, nullptr); } |
| 110 | 111 |
| 111 class DeferredCommands; | 112 class DeferredCommands; |
| 112 | 113 |
| 113 protected: | 114 protected: |
| 114 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_RETHROW }; | 115 enum Command { |
| 116 CMD_BREAK, |
| 117 CMD_CONTINUE, |
| 118 CMD_RETURN, |
| 119 CMD_ASYNC_RETURN, |
| 120 CMD_RETHROW |
| 121 }; |
| 115 void PerformCommand(Command command, Statement* statement); | 122 void PerformCommand(Command command, Statement* statement); |
| 116 virtual bool Execute(Command command, Statement* statement) = 0; | 123 virtual bool Execute(Command command, Statement* statement) = 0; |
| 117 | 124 |
| 118 BytecodeGenerator* generator() const { return generator_; } | 125 BytecodeGenerator* generator() const { return generator_; } |
| 119 ControlScope* outer() const { return outer_; } | 126 ControlScope* outer() const { return outer_; } |
| 120 ContextScope* context() const { return context_; } | 127 ContextScope* context() const { return context_; } |
| 121 | 128 |
| 122 private: | 129 private: |
| 123 BytecodeGenerator* generator_; | 130 BytecodeGenerator* generator_; |
| 124 ControlScope* outer_; | 131 ControlScope* outer_; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 | 221 |
| 215 protected: | 222 protected: |
| 216 bool Execute(Command command, Statement* statement) override { | 223 bool Execute(Command command, Statement* statement) override { |
| 217 switch (command) { | 224 switch (command) { |
| 218 case CMD_BREAK: // We should never see break/continue in top-level. | 225 case CMD_BREAK: // We should never see break/continue in top-level. |
| 219 case CMD_CONTINUE: | 226 case CMD_CONTINUE: |
| 220 UNREACHABLE(); | 227 UNREACHABLE(); |
| 221 case CMD_RETURN: | 228 case CMD_RETURN: |
| 222 generator()->BuildReturn(); | 229 generator()->BuildReturn(); |
| 223 return true; | 230 return true; |
| 231 case CMD_ASYNC_RETURN: |
| 232 generator()->BuildAsyncReturn(); |
| 233 return true; |
| 224 case CMD_RETHROW: | 234 case CMD_RETHROW: |
| 225 generator()->BuildReThrow(); | 235 generator()->BuildReThrow(); |
| 226 return true; | 236 return true; |
| 227 } | 237 } |
| 228 return false; | 238 return false; |
| 229 } | 239 } |
| 230 }; | 240 }; |
| 231 | 241 |
| 232 // Scoped class for enabling break inside blocks and switch blocks. | 242 // Scoped class for enabling break inside blocks and switch blocks. |
| 233 class BytecodeGenerator::ControlScopeForBreakable final | 243 class BytecodeGenerator::ControlScopeForBreakable final |
| 234 : public BytecodeGenerator::ControlScope { | 244 : public BytecodeGenerator::ControlScope { |
| 235 public: | 245 public: |
| 236 ControlScopeForBreakable(BytecodeGenerator* generator, | 246 ControlScopeForBreakable(BytecodeGenerator* generator, |
| 237 BreakableStatement* statement, | 247 BreakableStatement* statement, |
| 238 BreakableControlFlowBuilder* control_builder) | 248 BreakableControlFlowBuilder* control_builder) |
| 239 : ControlScope(generator), | 249 : ControlScope(generator), |
| 240 statement_(statement), | 250 statement_(statement), |
| 241 control_builder_(control_builder) {} | 251 control_builder_(control_builder) {} |
| 242 | 252 |
| 243 protected: | 253 protected: |
| 244 bool Execute(Command command, Statement* statement) override { | 254 bool Execute(Command command, Statement* statement) override { |
| 245 if (statement != statement_) return false; | 255 if (statement != statement_) return false; |
| 246 switch (command) { | 256 switch (command) { |
| 247 case CMD_BREAK: | 257 case CMD_BREAK: |
| 248 control_builder_->Break(); | 258 control_builder_->Break(); |
| 249 return true; | 259 return true; |
| 250 case CMD_CONTINUE: | 260 case CMD_CONTINUE: |
| 251 case CMD_RETURN: | 261 case CMD_RETURN: |
| 262 case CMD_ASYNC_RETURN: |
| 252 case CMD_RETHROW: | 263 case CMD_RETHROW: |
| 253 break; | 264 break; |
| 254 } | 265 } |
| 255 return false; | 266 return false; |
| 256 } | 267 } |
| 257 | 268 |
| 258 private: | 269 private: |
| 259 Statement* statement_; | 270 Statement* statement_; |
| 260 BreakableControlFlowBuilder* control_builder_; | 271 BreakableControlFlowBuilder* control_builder_; |
| 261 }; | 272 }; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 279 bool Execute(Command command, Statement* statement) override { | 290 bool Execute(Command command, Statement* statement) override { |
| 280 if (statement != statement_) return false; | 291 if (statement != statement_) return false; |
| 281 switch (command) { | 292 switch (command) { |
| 282 case CMD_BREAK: | 293 case CMD_BREAK: |
| 283 loop_builder_->Break(); | 294 loop_builder_->Break(); |
| 284 return true; | 295 return true; |
| 285 case CMD_CONTINUE: | 296 case CMD_CONTINUE: |
| 286 loop_builder_->Continue(); | 297 loop_builder_->Continue(); |
| 287 return true; | 298 return true; |
| 288 case CMD_RETURN: | 299 case CMD_RETURN: |
| 300 case CMD_ASYNC_RETURN: |
| 289 case CMD_RETHROW: | 301 case CMD_RETHROW: |
| 290 break; | 302 break; |
| 291 } | 303 } |
| 292 return false; | 304 return false; |
| 293 } | 305 } |
| 294 | 306 |
| 295 private: | 307 private: |
| 296 Statement* statement_; | 308 Statement* statement_; |
| 297 LoopBuilder* loop_builder_; | 309 LoopBuilder* loop_builder_; |
| 298 }; | 310 }; |
| 299 | 311 |
| 300 // Scoped class for enabling 'throw' in try-catch constructs. | 312 // Scoped class for enabling 'throw' in try-catch constructs. |
| 301 class BytecodeGenerator::ControlScopeForTryCatch final | 313 class BytecodeGenerator::ControlScopeForTryCatch final |
| 302 : public BytecodeGenerator::ControlScope { | 314 : public BytecodeGenerator::ControlScope { |
| 303 public: | 315 public: |
| 304 ControlScopeForTryCatch(BytecodeGenerator* generator, | 316 ControlScopeForTryCatch(BytecodeGenerator* generator, |
| 305 TryCatchBuilder* try_catch_builder) | 317 TryCatchBuilder* try_catch_builder) |
| 306 : ControlScope(generator) {} | 318 : ControlScope(generator) {} |
| 307 | 319 |
| 308 protected: | 320 protected: |
| 309 bool Execute(Command command, Statement* statement) override { | 321 bool Execute(Command command, Statement* statement) override { |
| 310 switch (command) { | 322 switch (command) { |
| 311 case CMD_BREAK: | 323 case CMD_BREAK: |
| 312 case CMD_CONTINUE: | 324 case CMD_CONTINUE: |
| 313 case CMD_RETURN: | 325 case CMD_RETURN: |
| 326 case CMD_ASYNC_RETURN: |
| 314 break; | 327 break; |
| 315 case CMD_RETHROW: | 328 case CMD_RETHROW: |
| 316 generator()->BuildReThrow(); | 329 generator()->BuildReThrow(); |
| 317 return true; | 330 return true; |
| 318 } | 331 } |
| 319 return false; | 332 return false; |
| 320 } | 333 } |
| 321 }; | 334 }; |
| 322 | 335 |
| 323 // Scoped class for enabling control flow through try-finally constructs. | 336 // Scoped class for enabling control flow through try-finally constructs. |
| 324 class BytecodeGenerator::ControlScopeForTryFinally final | 337 class BytecodeGenerator::ControlScopeForTryFinally final |
| 325 : public BytecodeGenerator::ControlScope { | 338 : public BytecodeGenerator::ControlScope { |
| 326 public: | 339 public: |
| 327 ControlScopeForTryFinally(BytecodeGenerator* generator, | 340 ControlScopeForTryFinally(BytecodeGenerator* generator, |
| 328 TryFinallyBuilder* try_finally_builder, | 341 TryFinallyBuilder* try_finally_builder, |
| 329 DeferredCommands* commands) | 342 DeferredCommands* commands) |
| 330 : ControlScope(generator), | 343 : ControlScope(generator), |
| 331 try_finally_builder_(try_finally_builder), | 344 try_finally_builder_(try_finally_builder), |
| 332 commands_(commands) {} | 345 commands_(commands) {} |
| 333 | 346 |
| 334 protected: | 347 protected: |
| 335 bool Execute(Command command, Statement* statement) override { | 348 bool Execute(Command command, Statement* statement) override { |
| 336 switch (command) { | 349 switch (command) { |
| 337 case CMD_BREAK: | 350 case CMD_BREAK: |
| 338 case CMD_CONTINUE: | 351 case CMD_CONTINUE: |
| 339 case CMD_RETURN: | 352 case CMD_RETURN: |
| 353 case CMD_ASYNC_RETURN: |
| 340 case CMD_RETHROW: | 354 case CMD_RETHROW: |
| 341 commands_->RecordCommand(command, statement); | 355 commands_->RecordCommand(command, statement); |
| 342 try_finally_builder_->LeaveTry(); | 356 try_finally_builder_->LeaveTry(); |
| 343 return true; | 357 return true; |
| 344 } | 358 } |
| 345 return false; | 359 return false; |
| 346 } | 360 } |
| 347 | 361 |
| 348 private: | 362 private: |
| 349 TryFinallyBuilder* try_finally_builder_; | 363 TryFinallyBuilder* try_finally_builder_; |
| (...skipping 701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 } | 1065 } |
| 1052 | 1066 |
| 1053 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 1067 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
| 1054 builder()->SetStatementPosition(stmt); | 1068 builder()->SetStatementPosition(stmt); |
| 1055 execution_control()->Break(stmt->target()); | 1069 execution_control()->Break(stmt->target()); |
| 1056 } | 1070 } |
| 1057 | 1071 |
| 1058 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 1072 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
| 1059 builder()->SetStatementPosition(stmt); | 1073 builder()->SetStatementPosition(stmt); |
| 1060 VisitForAccumulatorValue(stmt->expression()); | 1074 VisitForAccumulatorValue(stmt->expression()); |
| 1061 execution_control()->ReturnAccumulator(); | 1075 |
| 1076 if (stmt->is_async_return()) { |
| 1077 execution_control()->AsyncReturnAccumulator(); |
| 1078 } else { |
| 1079 execution_control()->ReturnAccumulator(); |
| 1080 } |
| 1062 } | 1081 } |
| 1063 | 1082 |
| 1064 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 1083 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
| 1065 builder()->SetStatementPosition(stmt); | 1084 builder()->SetStatementPosition(stmt); |
| 1066 VisitForAccumulatorValue(stmt->expression()); | 1085 VisitForAccumulatorValue(stmt->expression()); |
| 1067 BuildNewLocalWithContext(stmt->scope()); | 1086 BuildNewLocalWithContext(stmt->scope()); |
| 1068 VisitInScope(stmt->statement(), stmt->scope()); | 1087 VisitInScope(stmt->statement(), stmt->scope()); |
| 1069 } | 1088 } |
| 1070 | 1089 |
| 1071 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 1090 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
| (...skipping 922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1994 if (FLAG_trace) { | 2013 if (FLAG_trace) { |
| 1995 RegisterAllocationScope register_scope(this); | 2014 RegisterAllocationScope register_scope(this); |
| 1996 Register result = register_allocator()->NewRegister(); | 2015 Register result = register_allocator()->NewRegister(); |
| 1997 // Runtime returns {result} value, preserving accumulator. | 2016 // Runtime returns {result} value, preserving accumulator. |
| 1998 builder()->StoreAccumulatorInRegister(result).CallRuntime( | 2017 builder()->StoreAccumulatorInRegister(result).CallRuntime( |
| 1999 Runtime::kTraceExit, result); | 2018 Runtime::kTraceExit, result); |
| 2000 } | 2019 } |
| 2001 builder()->Return(); | 2020 builder()->Return(); |
| 2002 } | 2021 } |
| 2003 | 2022 |
| 2023 void BytecodeGenerator::BuildAsyncReturn() { |
| 2024 DCHECK(IsAsyncFunction(info()->literal()->kind())); |
| 2025 RegisterAllocationScope register_scope(this); |
| 2026 RegisterList args = register_allocator()->NewRegisterList(3); |
| 2027 Register receiver = args[0]; |
| 2028 Register promise = args[1]; |
| 2029 Register return_value = args[2]; |
| 2030 builder()->StoreAccumulatorInRegister(return_value); |
| 2031 |
| 2032 Variable* var_promise = scope()->promise_var(); |
| 2033 DCHECK_NOT_NULL(var_promise); |
| 2034 BuildVariableLoad(var_promise, FeedbackSlot::Invalid(), |
| 2035 HoleCheckMode::kElided); |
| 2036 builder() |
| 2037 ->StoreAccumulatorInRegister(promise) |
| 2038 .LoadUndefined() |
| 2039 .StoreAccumulatorInRegister(receiver) |
| 2040 .CallJSRuntime(Context::PROMISE_RESOLVE_INDEX, args) |
| 2041 .LoadAccumulatorWithRegister(promise); |
| 2042 BuildReturn(); |
| 2043 } |
| 2044 |
| 2004 void BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); } | 2045 void BytecodeGenerator::BuildReThrow() { builder()->ReThrow(); } |
| 2005 | 2046 |
| 2006 void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) { | 2047 void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) { |
| 2007 RegisterAllocationScope register_scope(this); | 2048 RegisterAllocationScope register_scope(this); |
| 2008 Register reason = register_allocator()->NewRegister(); | 2049 Register reason = register_allocator()->NewRegister(); |
| 2009 builder() | 2050 builder() |
| 2010 ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason))) | 2051 ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason))) |
| 2011 .StoreAccumulatorInRegister(reason) | 2052 .StoreAccumulatorInRegister(reason) |
| 2012 .CallRuntime(Runtime::kAbort, reason); | 2053 .CallRuntime(Runtime::kAbort, reason); |
| 2013 } | 2054 } |
| (...skipping 1367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3381 } | 3422 } |
| 3382 | 3423 |
| 3383 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3424 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
| 3384 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3425 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
| 3385 : Runtime::kStoreKeyedToSuper_Sloppy; | 3426 : Runtime::kStoreKeyedToSuper_Sloppy; |
| 3386 } | 3427 } |
| 3387 | 3428 |
| 3388 } // namespace interpreter | 3429 } // namespace interpreter |
| 3389 } // namespace internal | 3430 } // namespace internal |
| 3390 } // namespace v8 | 3431 } // namespace v8 |
| OLD | NEW |