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/compiler.h" | 8 #include "src/compiler.h" |
9 #include "src/interpreter/bytecode-register-allocator.h" | 9 #include "src/interpreter/bytecode-register-allocator.h" |
10 #include "src/interpreter/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
81 class BytecodeGenerator::ControlScope BASE_EMBEDDED { | 81 class BytecodeGenerator::ControlScope BASE_EMBEDDED { |
82 public: | 82 public: |
83 explicit ControlScope(BytecodeGenerator* generator) | 83 explicit ControlScope(BytecodeGenerator* generator) |
84 : generator_(generator), outer_(generator->execution_control()) { | 84 : generator_(generator), outer_(generator->execution_control()) { |
85 generator_->set_execution_control(this); | 85 generator_->set_execution_control(this); |
86 } | 86 } |
87 virtual ~ControlScope() { generator_->set_execution_control(outer()); } | 87 virtual ~ControlScope() { generator_->set_execution_control(outer()); } |
88 | 88 |
89 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); } | 89 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); } |
90 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); } | 90 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); } |
91 void ReturnAccumulator() { PerformCommand(CMD_RETURN, nullptr); } | |
92 void ReThrowAccumulator() { PerformCommand(CMD_RETHROW, nullptr); } | |
93 | |
94 class DeferredCommands; | |
91 | 95 |
92 protected: | 96 protected: |
93 enum Command { CMD_BREAK, CMD_CONTINUE }; | 97 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_RETHROW }; |
94 void PerformCommand(Command command, Statement* statement); | 98 void PerformCommand(Command command, Statement* statement); |
95 virtual bool Execute(Command command, Statement* statement) = 0; | 99 virtual bool Execute(Command command, Statement* statement) = 0; |
96 | 100 |
97 BytecodeGenerator* generator() const { return generator_; } | 101 BytecodeGenerator* generator() const { return generator_; } |
98 ControlScope* outer() const { return outer_; } | 102 ControlScope* outer() const { return outer_; } |
99 | 103 |
100 private: | 104 private: |
101 BytecodeGenerator* generator_; | 105 BytecodeGenerator* generator_; |
102 ControlScope* outer_; | 106 ControlScope* outer_; |
103 | 107 |
104 DISALLOW_COPY_AND_ASSIGN(ControlScope); | 108 DISALLOW_COPY_AND_ASSIGN(ControlScope); |
105 }; | 109 }; |
106 | 110 |
107 | 111 |
112 // Helper class for a try-finally control scope. It can record intercepted | |
113 // control-flow commands that cause entry into a finally-block, and re-apply | |
114 // them after again leaving that block. Special tokens are used to identify | |
115 // paths going through the finally-block to dispatch after leaving the block. | |
116 class BytecodeGenerator::ControlScope::DeferredCommands final { | |
117 public: | |
118 DeferredCommands(BytecodeGenerator* generator, Register token_register, | |
119 Register result_register) | |
120 : generator_(generator), | |
121 deferred_(generator->zone()), | |
122 token_register_(token_register), | |
123 result_register_(result_register) {} | |
124 | |
125 // One recorded control-flow command. | |
126 struct Entry { | |
127 Command command; // The command type being applied on this path. | |
128 Statement* statement; // The target statement for the command or {nullptr}. | |
129 int token; // A token identifying this particular path. | |
130 }; | |
131 | |
132 // Records a control-flow command while entering the finally-block. This also | |
133 // generates a new dispatch token that identifies one particular path. This | |
134 // expects the result to be in the accumulator. | |
135 void RecordCommand(Command command, Statement* statement) { | |
136 int token = static_cast<int>(deferred_.size()); | |
137 deferred_.push_back({command, statement, token}); | |
138 | |
139 builder()->StoreAccumulatorInRegister(result_register_); | |
140 builder()->LoadLiteral(Smi::FromInt(token)); | |
141 builder()->StoreAccumulatorInRegister(token_register_); | |
142 } | |
143 | |
144 // Records the dispatch token to be used to identify the re-throw path when | |
145 // the finally-block has been entered through the exception handler. This | |
146 // expects the exception to be in the accumulator. | |
147 void RecordHandlerReThrowPath() { | |
148 // The accumulator contains the exception object. | |
149 RecordCommand(CMD_RETHROW, nullptr); | |
150 } | |
151 | |
152 // Records the dispatch token to be used to identify the implicit fall-through | |
153 // path at the end of a try-block into the corresponding finally-block. | |
154 void RecordFallThroughPath() { | |
155 builder()->LoadLiteral(Smi::FromInt(-1)); | |
156 builder()->StoreAccumulatorInRegister(token_register_); | |
157 } | |
158 | |
159 // Applies all recorded control-flow commands after the finally-block again. | |
160 // This generates a dynamic dispatch on the token from the entry point. | |
161 void ApplyDeferredCommands() { | |
162 // The fall-through path is covered by the default case, hence +1 here. | |
163 SwitchBuilder dispatch(builder(), static_cast<int>(deferred_.size() + 1)); | |
164 for (size_t i = 0; i < deferred_.size(); ++i) { | |
165 Entry& entry = deferred_[i]; | |
166 builder()->LoadLiteral(Smi::FromInt(entry.token)); | |
167 builder()->CompareOperation(Token::EQ_STRICT, token_register_, | |
168 Strength::WEAK); | |
169 dispatch.Case(static_cast<int>(i)); | |
170 } | |
171 dispatch.DefaultAt(static_cast<int>(deferred_.size())); | |
172 for (size_t i = 0; i < deferred_.size(); ++i) { | |
173 Entry& entry = deferred_[i]; | |
174 dispatch.SetCaseTarget(static_cast<int>(i)); | |
175 builder()->LoadAccumulatorWithRegister(result_register_); | |
176 execution_control()->PerformCommand(entry.command, entry.statement); | |
177 } | |
178 dispatch.SetCaseTarget(static_cast<int>(deferred_.size())); | |
179 } | |
180 | |
181 BytecodeArrayBuilder* builder() { return generator_->builder(); } | |
182 ControlScope* execution_control() { return generator_->execution_control(); } | |
183 | |
184 private: | |
185 BytecodeGenerator* generator_; | |
186 ZoneVector<Entry> deferred_; | |
187 Register token_register_; | |
188 Register result_register_; | |
189 }; | |
190 | |
191 | |
192 // Scoped class for dealing with control flow reaching the function level. | |
193 class BytecodeGenerator::ControlScopeForTopLevel final | |
194 : public BytecodeGenerator::ControlScope { | |
195 public: | |
196 explicit ControlScopeForTopLevel(BytecodeGenerator* generator) | |
197 : ControlScope(generator) {} | |
198 | |
199 protected: | |
200 virtual bool Execute(Command command, Statement* statement) { | |
rmcilroy
2016/01/22 11:44:11
/s/virtual/override (I've changed the existing one
Michael Starzinger
2016/01/22 11:55:34
Done.
| |
201 switch (command) { | |
202 case CMD_BREAK: | |
203 case CMD_CONTINUE: | |
204 break; | |
205 case CMD_RETURN: | |
206 generator()->builder()->Return(); | |
207 return true; | |
208 case CMD_RETHROW: | |
209 // TODO(mstarzinger): Should be a ReThrow instead. | |
210 generator()->builder()->Throw(); | |
211 return true; | |
212 } | |
213 return false; | |
214 } | |
215 }; | |
216 | |
217 | |
108 // Scoped class for enabling break inside blocks and switch blocks. | 218 // Scoped class for enabling break inside blocks and switch blocks. |
109 class BytecodeGenerator::ControlScopeForBreakable final | 219 class BytecodeGenerator::ControlScopeForBreakable final |
110 : public BytecodeGenerator::ControlScope { | 220 : public BytecodeGenerator::ControlScope { |
111 public: | 221 public: |
112 ControlScopeForBreakable(BytecodeGenerator* generator, | 222 ControlScopeForBreakable(BytecodeGenerator* generator, |
113 BreakableStatement* statement, | 223 BreakableStatement* statement, |
114 BreakableControlFlowBuilder* control_builder) | 224 BreakableControlFlowBuilder* control_builder) |
115 : ControlScope(generator), | 225 : ControlScope(generator), |
116 statement_(statement), | 226 statement_(statement), |
117 control_builder_(control_builder) {} | 227 control_builder_(control_builder) {} |
118 | 228 |
119 protected: | 229 protected: |
120 virtual bool Execute(Command command, Statement* statement) { | 230 virtual bool Execute(Command command, Statement* statement) { |
121 if (statement != statement_) return false; | 231 if (statement != statement_) return false; |
122 switch (command) { | 232 switch (command) { |
123 case CMD_BREAK: | 233 case CMD_BREAK: |
124 control_builder_->Break(); | 234 control_builder_->Break(); |
125 return true; | 235 return true; |
126 case CMD_CONTINUE: | 236 case CMD_CONTINUE: |
237 case CMD_RETURN: | |
238 case CMD_RETHROW: | |
127 break; | 239 break; |
128 } | 240 } |
129 return false; | 241 return false; |
130 } | 242 } |
131 | 243 |
132 private: | 244 private: |
133 Statement* statement_; | 245 Statement* statement_; |
134 BreakableControlFlowBuilder* control_builder_; | 246 BreakableControlFlowBuilder* control_builder_; |
135 }; | 247 }; |
136 | 248 |
(...skipping 13 matching lines...) Expand all Loading... | |
150 protected: | 262 protected: |
151 virtual bool Execute(Command command, Statement* statement) { | 263 virtual bool Execute(Command command, Statement* statement) { |
152 if (statement != statement_) return false; | 264 if (statement != statement_) return false; |
153 switch (command) { | 265 switch (command) { |
154 case CMD_BREAK: | 266 case CMD_BREAK: |
155 loop_builder_->Break(); | 267 loop_builder_->Break(); |
156 return true; | 268 return true; |
157 case CMD_CONTINUE: | 269 case CMD_CONTINUE: |
158 loop_builder_->Continue(); | 270 loop_builder_->Continue(); |
159 return true; | 271 return true; |
272 case CMD_RETURN: | |
273 case CMD_RETHROW: | |
274 break; | |
160 } | 275 } |
161 return false; | 276 return false; |
162 } | 277 } |
163 | 278 |
164 private: | 279 private: |
165 Statement* statement_; | 280 Statement* statement_; |
166 LoopBuilder* loop_builder_; | 281 LoopBuilder* loop_builder_; |
167 }; | 282 }; |
168 | 283 |
169 | 284 |
285 // Scoped class for enabling 'throw' in try-catch constructs. | |
286 class BytecodeGenerator::ControlScopeForTryCatch final | |
287 : public BytecodeGenerator::ControlScope { | |
288 public: | |
289 ControlScopeForTryCatch(BytecodeGenerator* generator, | |
290 TryCatchBuilder* try_catch_builder) | |
291 : ControlScope(generator), try_catch_builder_(try_catch_builder) {} | |
292 | |
293 protected: | |
294 virtual bool Execute(Command command, Statement* statement) { | |
rmcilroy
2016/01/22 11:44:11
ditto
Michael Starzinger
2016/01/22 11:55:34
Done.
| |
295 switch (command) { | |
296 case CMD_BREAK: | |
297 case CMD_CONTINUE: | |
298 case CMD_RETURN: | |
299 break; | |
300 case CMD_RETHROW: | |
301 // TODO(mstarzinger): Test and implement this! | |
302 USE(try_catch_builder_); | |
303 UNIMPLEMENTED(); | |
304 return true; | |
305 } | |
306 return false; | |
307 } | |
308 | |
309 private: | |
310 TryCatchBuilder* try_catch_builder_; | |
311 }; | |
312 | |
313 | |
314 // Scoped class for enabling control flow through try-finally constructs. | |
315 class BytecodeGenerator::ControlScopeForTryFinally final | |
316 : public BytecodeGenerator::ControlScope { | |
317 public: | |
318 ControlScopeForTryFinally(BytecodeGenerator* generator, | |
319 TryFinallyBuilder* try_finally_builder, | |
320 DeferredCommands* commands) | |
321 : ControlScope(generator), | |
322 try_finally_builder_(try_finally_builder), | |
323 commands_(commands) {} | |
324 | |
325 protected: | |
326 virtual bool Execute(Command command, Statement* statement) { | |
rmcilroy
2016/01/22 11:44:11
ditto
Michael Starzinger
2016/01/22 11:55:34
Done.
| |
327 switch (command) { | |
328 case CMD_BREAK: | |
329 case CMD_CONTINUE: | |
330 case CMD_RETURN: | |
331 case CMD_RETHROW: | |
332 commands_->RecordCommand(command, statement); | |
333 try_finally_builder_->LeaveTry(); | |
334 return true; | |
335 } | |
336 return false; | |
337 } | |
338 | |
339 private: | |
340 TryFinallyBuilder* try_finally_builder_; | |
341 DeferredCommands* commands_; | |
342 }; | |
343 | |
344 | |
170 void BytecodeGenerator::ControlScope::PerformCommand(Command command, | 345 void BytecodeGenerator::ControlScope::PerformCommand(Command command, |
171 Statement* statement) { | 346 Statement* statement) { |
172 ControlScope* current = this; | 347 ControlScope* current = this; |
173 do { | 348 do { |
174 if (current->Execute(command, statement)) return; | 349 if (current->Execute(command, statement)) return; |
175 current = current->outer(); | 350 current = current->outer(); |
176 } while (current != nullptr); | 351 } while (current != nullptr); |
177 UNREACHABLE(); | 352 UNREACHABLE(); |
178 } | 353 } |
179 | 354 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 } | 533 } |
359 | 534 |
360 | 535 |
361 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { | 536 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { |
362 set_info(info); | 537 set_info(info); |
363 set_scope(info->scope()); | 538 set_scope(info->scope()); |
364 | 539 |
365 // Initialize the incoming context. | 540 // Initialize the incoming context. |
366 ContextScope incoming_context(this, scope(), false); | 541 ContextScope incoming_context(this, scope(), false); |
367 | 542 |
543 // Initialize control scope. | |
544 ControlScopeForTopLevel control(this); | |
545 | |
368 builder()->set_parameter_count(info->num_parameters_including_this()); | 546 builder()->set_parameter_count(info->num_parameters_including_this()); |
369 builder()->set_locals_count(scope()->num_stack_slots()); | 547 builder()->set_locals_count(scope()->num_stack_slots()); |
370 builder()->set_context_count(scope()->MaxNestedContextChainLength()); | 548 builder()->set_context_count(scope()->MaxNestedContextChainLength()); |
371 | 549 |
372 // Build function context only if there are context allocated variables. | 550 // Build function context only if there are context allocated variables. |
373 if (scope()->NeedsContext()) { | 551 if (scope()->NeedsContext()) { |
374 // Push a new inner context scope for the function. | 552 // Push a new inner context scope for the function. |
375 VisitNewLocalFunctionContext(); | 553 VisitNewLocalFunctionContext(); |
376 ContextScope local_function_context(this, scope(), false); | 554 ContextScope local_function_context(this, scope(), false); |
377 VisitBuildLocalActivationContext(); | 555 VisitBuildLocalActivationContext(); |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
654 } | 832 } |
655 | 833 |
656 | 834 |
657 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 835 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
658 execution_control()->Break(stmt->target()); | 836 execution_control()->Break(stmt->target()); |
659 } | 837 } |
660 | 838 |
661 | 839 |
662 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 840 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
663 VisitForAccumulatorValue(stmt->expression()); | 841 VisitForAccumulatorValue(stmt->expression()); |
664 builder()->Return(); | 842 execution_control()->ReturnAccumulator(); |
665 } | 843 } |
666 | 844 |
667 | 845 |
668 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 846 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
669 UNIMPLEMENTED(); | 847 UNIMPLEMENTED(); |
670 } | 848 } |
671 | 849 |
672 | 850 |
673 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 851 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
674 // We need this scope because we visit for register values. We have to | 852 // We need this scope because we visit for register values. We have to |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
902 TryCatchBuilder try_control_builder(builder()); | 1080 TryCatchBuilder try_control_builder(builder()); |
903 | 1081 |
904 // Preserve the context in a dedicated register, so that it can be restored | 1082 // Preserve the context in a dedicated register, so that it can be restored |
905 // when the handler is entered by the stack-unwinding machinery. | 1083 // when the handler is entered by the stack-unwinding machinery. |
906 // TODO(mstarzinger): Be smarter about register allocation. | 1084 // TODO(mstarzinger): Be smarter about register allocation. |
907 Register context = register_allocator()->NewRegister(); | 1085 Register context = register_allocator()->NewRegister(); |
908 | 1086 |
909 // Evaluate the try-block inside a control scope. This simulates a handler | 1087 // Evaluate the try-block inside a control scope. This simulates a handler |
910 // that is intercepting 'throw' control commands. | 1088 // that is intercepting 'throw' control commands. |
911 try_control_builder.BeginTry(context); | 1089 try_control_builder.BeginTry(context); |
912 // TODO(mstarzinger): Control scope is missing! | 1090 { |
913 Visit(stmt->try_block()); | 1091 ControlScopeForTryCatch scope(this, &try_control_builder); |
1092 Visit(stmt->try_block()); | |
1093 } | |
914 try_control_builder.EndTry(); | 1094 try_control_builder.EndTry(); |
915 | 1095 |
916 // Clear message object as we enter the catch block. | 1096 // Clear message object as we enter the catch block. |
917 // TODO(mstarzinger): Implement this! | 1097 // TODO(mstarzinger): Implement this! |
918 | 1098 |
919 // Create a catch scope that binds the exception. | 1099 // Create a catch scope that binds the exception. |
920 VisitNewLocalCatchContext(stmt->variable()); | 1100 VisitNewLocalCatchContext(stmt->variable()); |
921 | 1101 |
922 // Evaluate the catch-block. | 1102 // Evaluate the catch-block. |
923 VisitInScope(stmt->catch_block(), stmt->scope()); | 1103 VisitInScope(stmt->catch_block(), stmt->scope()); |
924 try_control_builder.EndCatch(); | 1104 try_control_builder.EndCatch(); |
925 } | 1105 } |
926 | 1106 |
927 | 1107 |
928 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 1108 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
929 TryFinallyBuilder try_control_builder(builder()); | 1109 TryFinallyBuilder try_control_builder(builder()); |
930 | 1110 |
1111 // We keep a record of all paths that enter the finally-block to be able to | |
1112 // dispatch to the correct continuation point after the statements in the | |
1113 // finally-block have been evaluated. | |
1114 // | |
1115 // The try-finally construct can enter the finally-block in three ways: | |
1116 // 1. By exiting the try-block normally, falling through at the end. | |
1117 // 2. By exiting the try-block with a function-local control flow transfer | |
1118 // (i.e. through break/continue/return statements). | |
1119 // 3. By exiting the try-block with a thrown exception. | |
1120 // | |
1121 // The result register semantics depend on how the block was entered: | |
1122 // - ReturnStatement: It represents the return value being returned. | |
1123 // - ThrowStatement: It represents the exception being thrown. | |
1124 // - BreakStatement/ContinueStatement: Undefined and not used. | |
1125 // - Falling through into finally-block: Undefined and not used. | |
1126 Register token = register_allocator()->NewRegister(); | |
1127 Register result = register_allocator()->NewRegister(); | |
1128 ControlScope::DeferredCommands commands(this, token, result); | |
1129 | |
931 // Preserve the context in a dedicated register, so that it can be restored | 1130 // Preserve the context in a dedicated register, so that it can be restored |
932 // when the handler is entered by the stack-unwinding machinery. | 1131 // when the handler is entered by the stack-unwinding machinery. |
933 // TODO(mstarzinger): Be smarter about register allocation. | 1132 // TODO(mstarzinger): Be smarter about register allocation. |
934 Register context = register_allocator()->NewRegister(); | 1133 Register context = register_allocator()->NewRegister(); |
935 | 1134 |
936 // Evaluate the try-block inside a control scope. This simulates a handler | 1135 // Evaluate the try-block inside a control scope. This simulates a handler |
937 // that is intercepting all control commands. | 1136 // that is intercepting all control commands. |
938 try_control_builder.BeginTry(context); | 1137 try_control_builder.BeginTry(context); |
939 // TODO(mstarzinger): Control scope is missing! | 1138 { |
940 Visit(stmt->try_block()); | 1139 ControlScopeForTryFinally scope(this, &try_control_builder, &commands); |
1140 Visit(stmt->try_block()); | |
1141 } | |
941 try_control_builder.EndTry(); | 1142 try_control_builder.EndTry(); |
942 | 1143 |
1144 // Record fall-through and exception cases. | |
1145 commands.RecordFallThroughPath(); | |
1146 try_control_builder.LeaveTry(); | |
1147 try_control_builder.BeginHandler(); | |
1148 commands.RecordHandlerReThrowPath(); | |
1149 | |
1150 try_control_builder.BeginFinally(); | |
1151 | |
943 // Clear message object as we enter the finally block. | 1152 // Clear message object as we enter the finally block. |
944 // TODO(mstarzinger): Implement this! | 1153 // TODO(mstarzinger): Implement this! |
945 | 1154 |
946 // Evaluate the finally-block. | 1155 // Evaluate the finally-block. |
947 Visit(stmt->finally_block()); | 1156 Visit(stmt->finally_block()); |
948 try_control_builder.EndFinally(); | 1157 try_control_builder.EndFinally(); |
1158 | |
1159 // Dynamic dispatch after the finally-block. | |
1160 commands.ApplyDeferredCommands(); | |
949 } | 1161 } |
950 | 1162 |
951 | 1163 |
952 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { | 1164 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) { |
953 UNIMPLEMENTED(); | 1165 UNIMPLEMENTED(); |
954 } | 1166 } |
955 | 1167 |
956 | 1168 |
957 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 1169 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
958 // Find or build a shared function info. | 1170 // Find or build a shared function info. |
(...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2278 } | 2490 } |
2279 | 2491 |
2280 | 2492 |
2281 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2493 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
2282 return info()->feedback_vector()->GetIndex(slot); | 2494 return info()->feedback_vector()->GetIndex(slot); |
2283 } | 2495 } |
2284 | 2496 |
2285 } // namespace interpreter | 2497 } // namespace interpreter |
2286 } // namespace internal | 2498 } // namespace internal |
2287 } // namespace v8 | 2499 } // namespace v8 |
OLD | NEW |