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 |