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/compiler/bytecode-graph-builder.h" | 5 #include "src/compiler/bytecode-graph-builder.h" |
6 | 6 |
7 #include "src/compiler/bytecode-branch-analysis.h" | 7 #include "src/compiler/bytecode-branch-analysis.h" |
8 #include "src/compiler/linkage.h" | 8 #include "src/compiler/linkage.h" |
9 #include "src/compiler/operator-properties.h" | 9 #include "src/compiler/operator-properties.h" |
10 #include "src/interpreter/bytecodes.h" | 10 #include "src/interpreter/bytecodes.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 namespace compiler { | 14 namespace compiler { |
15 | 15 |
16 // Helper for generating frame states for before and after a bytecode. | 16 // Helper for generating frame states for before and after a bytecode. |
17 class BytecodeGraphBuilder::FrameStateBeforeAndAfter { | 17 class BytecodeGraphBuilder::FrameStateBeforeAndAfter { |
18 public: | 18 public: |
19 FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder, | 19 FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder, |
20 const interpreter::BytecodeArrayIterator& iterator) | 20 const interpreter::BytecodeArrayIterator& iterator) |
21 : builder_(builder), id_after_(BailoutId::None()) { | 21 : builder_(builder), |
22 id_after_(BailoutId::None()), | |
23 added_to_node_(false), | |
24 output_poke_offset_(0), | |
25 output_poke_count_(0) { | |
22 BailoutId id_before(iterator.current_offset()); | 26 BailoutId id_before(iterator.current_offset()); |
23 frame_state_before_ = builder_->environment()->Checkpoint( | 27 frame_state_before_ = builder_->environment()->Checkpoint( |
24 id_before, AccumulatorUpdateMode::kOutputIgnored); | 28 id_before, OutputFrameStateCombine::Ignore()); |
25 id_after_ = BailoutId(id_before.ToInt() + iterator.current_bytecode_size()); | 29 id_after_ = BailoutId(id_before.ToInt() + iterator.current_bytecode_size()); |
26 } | 30 } |
27 | 31 |
28 ~FrameStateBeforeAndAfter() { | 32 ~FrameStateBeforeAndAfter() { |
29 DCHECK(builder_->environment()->StateValuesAreUpToDate( | 33 DCHECK(added_to_node_); |
30 accumulator_update_mode_)); | 34 DCHECK(builder_->environment()->StateValuesAreUpToDate(output_poke_offset_, |
35 output_poke_count_)); | |
31 } | 36 } |
32 | 37 |
33 private: | 38 private: |
34 friend class Environment; | 39 friend class Environment; |
35 | 40 |
36 void AddToNode(Node* node, AccumulatorUpdateMode update_mode) { | 41 void AddToNode(Node* node, OutputFrameStateCombine combine, int poke_count) { |
42 DCHECK(!added_to_node_); | |
37 int count = OperatorProperties::GetFrameStateInputCount(node->op()); | 43 int count = OperatorProperties::GetFrameStateInputCount(node->op()); |
38 DCHECK_LE(count, 2); | 44 DCHECK_LE(count, 2); |
39 if (count >= 1) { | 45 if (count >= 1) { |
40 // Add the frame state for after the operation. | 46 // Add the frame state for after the operation. |
41 DCHECK_EQ(IrOpcode::kDead, | 47 DCHECK_EQ(IrOpcode::kDead, |
42 NodeProperties::GetFrameStateInput(node, 0)->opcode()); | 48 NodeProperties::GetFrameStateInput(node, 0)->opcode()); |
43 Node* frame_state_after = | 49 Node* frame_state_after = |
44 builder_->environment()->Checkpoint(id_after_, update_mode); | 50 builder_->environment()->Checkpoint(id_after_, combine); |
45 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after); | 51 NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after); |
46 } | 52 } |
47 | 53 |
48 if (count >= 2) { | 54 if (count >= 2) { |
49 // Add the frame state for before the operation. | 55 // Add the frame state for before the operation. |
50 DCHECK_EQ(IrOpcode::kDead, | 56 DCHECK_EQ(IrOpcode::kDead, |
51 NodeProperties::GetFrameStateInput(node, 1)->opcode()); | 57 NodeProperties::GetFrameStateInput(node, 1)->opcode()); |
52 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_); | 58 NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_); |
53 } | 59 } |
54 accumulator_update_mode_ = update_mode; | 60 |
61 if (poke_count) { | |
62 DCHECK(!combine.IsOutputIgnored()); | |
63 output_poke_offset_ = static_cast<int>(combine.GetOffsetToPokeAt()); | |
64 output_poke_count_ = poke_count; | |
65 } | |
66 added_to_node_ = true; | |
55 } | 67 } |
56 | 68 |
57 BytecodeGraphBuilder* builder_; | 69 BytecodeGraphBuilder* builder_; |
58 Node* frame_state_before_; | 70 Node* frame_state_before_; |
59 BailoutId id_after_; | 71 BailoutId id_after_; |
60 AccumulatorUpdateMode accumulator_update_mode_; | 72 |
73 bool added_to_node_; | |
74 int output_poke_offset_; | |
75 int output_poke_count_; | |
61 }; | 76 }; |
62 | 77 |
63 | 78 |
64 // Issues: | 79 // Issues: |
65 // - Scopes - intimately tied to AST. Need to eval what is needed. | 80 // - Scopes - intimately tied to AST. Need to eval what is needed. |
66 // - Need to resolve closure parameter treatment. | 81 // - Need to resolve closure parameter treatment. |
67 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder, | 82 BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder, |
68 int register_count, | 83 int register_count, |
69 int parameter_count, | 84 int parameter_count, |
70 Node* control_dependency, | 85 Node* control_dependency, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
127 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( | 142 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( |
128 interpreter::Register the_register) const { | 143 interpreter::Register the_register) const { |
129 if (the_register.is_parameter()) { | 144 if (the_register.is_parameter()) { |
130 return the_register.ToParameterIndex(parameter_count()); | 145 return the_register.ToParameterIndex(parameter_count()); |
131 } else { | 146 } else { |
132 return the_register.index() + register_base(); | 147 return the_register.index() + register_base(); |
133 } | 148 } |
134 } | 149 } |
135 | 150 |
136 | 151 |
137 void BytecodeGraphBuilder::Environment::BindRegister( | 152 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { |
138 interpreter::Register the_register, Node* node) { | 153 return values()->at(accumulator_base_); |
139 int values_index = RegisterToValuesIndex(the_register); | |
140 values()->at(values_index) = node; | |
141 } | 154 } |
142 | 155 |
143 | 156 |
144 Node* BytecodeGraphBuilder::Environment::LookupRegister( | 157 Node* BytecodeGraphBuilder::Environment::LookupRegister( |
145 interpreter::Register the_register) const { | 158 interpreter::Register the_register) const { |
146 if (the_register.is_function_context()) { | 159 if (the_register.is_function_context()) { |
147 return builder()->GetFunctionContext(); | 160 return builder()->GetFunctionContext(); |
148 } else if (the_register.is_function_closure()) { | 161 } else if (the_register.is_function_closure()) { |
149 return builder()->GetFunctionClosure(); | 162 return builder()->GetFunctionClosure(); |
150 } else if (the_register.is_new_target()) { | 163 } else if (the_register.is_new_target()) { |
151 return builder()->GetNewTarget(); | 164 return builder()->GetNewTarget(); |
152 } else { | 165 } else { |
153 int values_index = RegisterToValuesIndex(the_register); | 166 int values_index = RegisterToValuesIndex(the_register); |
154 return values()->at(values_index); | 167 return values()->at(values_index); |
155 } | 168 } |
156 } | 169 } |
157 | 170 |
158 | 171 |
159 void BytecodeGraphBuilder::Environment::BindAccumulator( | |
160 Node* node, FrameStateBeforeAndAfter* states) { | |
161 if (states) { | |
162 states->AddToNode(node, AccumulatorUpdateMode::kOutputInAccumulator); | |
163 } | |
164 values()->at(accumulator_base_) = node; | |
165 } | |
166 | |
167 | |
168 void BytecodeGraphBuilder::Environment::RecordAfterState( | |
169 Node* node, FrameStateBeforeAndAfter* states) { | |
170 states->AddToNode(node, AccumulatorUpdateMode::kOutputIgnored); | |
171 } | |
172 | |
173 | |
174 void BytecodeGraphBuilder::Environment::ExchangeRegisters( | 172 void BytecodeGraphBuilder::Environment::ExchangeRegisters( |
175 interpreter::Register reg0, interpreter::Register reg1) { | 173 interpreter::Register reg0, interpreter::Register reg1) { |
176 int reg0_index = RegisterToValuesIndex(reg0); | 174 int reg0_index = RegisterToValuesIndex(reg0); |
177 int reg1_index = RegisterToValuesIndex(reg1); | 175 int reg1_index = RegisterToValuesIndex(reg1); |
178 Node* saved_reg0_value = values()->at(reg0_index); | 176 Node* saved_reg0_value = values()->at(reg0_index); |
179 values()->at(reg0_index) = values()->at(reg1_index); | 177 values()->at(reg0_index) = values()->at(reg1_index); |
180 values()->at(reg1_index) = saved_reg0_value; | 178 values()->at(reg1_index) = saved_reg0_value; |
181 } | 179 } |
182 | 180 |
183 | 181 |
184 Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const { | 182 void BytecodeGraphBuilder::Environment::BindAccumulator( |
185 return values()->at(accumulator_base_); | 183 Node* node, FrameStateBeforeAndAfter* states) { |
184 if (states) { | |
185 states->AddToNode(node, OutputFrameStateCombine::PokeAt(0), 1); | |
186 } | |
187 values()->at(accumulator_base_) = node; | |
186 } | 188 } |
187 | 189 |
188 | 190 |
191 void BytecodeGraphBuilder::Environment::BindRegister( | |
192 interpreter::Register the_register, Node* node, | |
193 FrameStateBeforeAndAfter* states) { | |
194 int values_index = RegisterToValuesIndex(the_register); | |
195 if (states) { | |
196 states->AddToNode( | |
197 node, OutputFrameStateCombine::PokeAt(accumulator_base_ - values_index), | |
198 1); | |
199 } | |
200 values()->at(values_index) = node; | |
201 } | |
202 | |
203 | |
204 void BytecodeGraphBuilder::Environment::BindRegistersToProjections( | |
205 interpreter::Register first_reg, Node* node, int count, | |
206 FrameStateBeforeAndAfter* states) { | |
207 int values_index = RegisterToValuesIndex(first_reg); | |
208 if (states) { | |
Jarin
2016/01/08 12:32:55
I think you should check that 'node->op()->ValueOu
rmcilroy
2016/01/08 14:47:20
Right, actually I think we should just use node->o
| |
209 states->AddToNode( | |
210 node, OutputFrameStateCombine::PokeAt(accumulator_base_ - values_index), | |
211 count); | |
212 } | |
213 for (int i = 0; i < count; i++) { | |
214 values()->at(values_index + i) = | |
215 builder()->NewNode(common()->Projection(i), node); | |
216 } | |
217 } | |
218 | |
219 | |
220 void BytecodeGraphBuilder::Environment::RecordAfterState( | |
221 Node* node, FrameStateBeforeAndAfter* states) { | |
222 states->AddToNode(node, OutputFrameStateCombine::Ignore(), 0); | |
223 } | |
224 | |
225 | |
189 bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const { | 226 bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const { |
190 return GetControlDependency()->opcode() == IrOpcode::kDead; | 227 return GetControlDependency()->opcode() == IrOpcode::kDead; |
191 } | 228 } |
192 | 229 |
193 | 230 |
194 void BytecodeGraphBuilder::Environment::MarkAsUnreachable() { | 231 void BytecodeGraphBuilder::Environment::MarkAsUnreachable() { |
195 UpdateControlDependency(builder()->jsgraph()->Dead()); | 232 UpdateControlDependency(builder()->jsgraph()->Dead()); |
196 } | 233 } |
197 | 234 |
198 | 235 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
283 int offset, | 320 int offset, |
284 int count) { | 321 int count) { |
285 if (StateValuesRequireUpdate(state_values, offset, count)) { | 322 if (StateValuesRequireUpdate(state_values, offset, count)) { |
286 const Operator* op = common()->StateValues(count); | 323 const Operator* op = common()->StateValues(count); |
287 (*state_values) = graph()->NewNode(op, count, &values()->at(offset)); | 324 (*state_values) = graph()->NewNode(op, count, &values()->at(offset)); |
288 } | 325 } |
289 } | 326 } |
290 | 327 |
291 | 328 |
292 Node* BytecodeGraphBuilder::Environment::Checkpoint( | 329 Node* BytecodeGraphBuilder::Environment::Checkpoint( |
293 BailoutId bailout_id, AccumulatorUpdateMode update_mode) { | 330 BailoutId bailout_id, OutputFrameStateCombine combine) { |
294 if (!builder()->info()->is_deoptimization_enabled()) { | 331 if (!builder()->info()->is_deoptimization_enabled()) { |
295 return builder()->jsgraph()->EmptyFrameState(); | 332 return builder()->jsgraph()->EmptyFrameState(); |
296 } | 333 } |
297 | 334 |
298 // TODO(rmcilroy): Consider using StateValuesCache for some state values. | 335 // TODO(rmcilroy): Consider using StateValuesCache for some state values. |
299 UpdateStateValues(¶meters_state_values_, 0, parameter_count()); | 336 UpdateStateValues(¶meters_state_values_, 0, parameter_count()); |
300 UpdateStateValues(®isters_state_values_, register_base(), | 337 UpdateStateValues(®isters_state_values_, register_base(), |
301 register_count()); | 338 register_count()); |
302 UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1); | 339 UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1); |
303 | 340 |
304 OutputFrameStateCombine combine = | |
305 update_mode == AccumulatorUpdateMode::kOutputIgnored | |
306 ? OutputFrameStateCombine::Ignore() | |
307 : OutputFrameStateCombine::PokeAt(0); | |
308 const Operator* op = common()->FrameState( | 341 const Operator* op = common()->FrameState( |
309 bailout_id, combine, builder()->frame_state_function_info()); | 342 bailout_id, combine, builder()->frame_state_function_info()); |
310 | |
311 Node* result = graph()->NewNode( | 343 Node* result = graph()->NewNode( |
312 op, parameters_state_values_, registers_state_values_, | 344 op, parameters_state_values_, registers_state_values_, |
313 accumulator_state_values_, Context(), builder()->GetFunctionClosure(), | 345 accumulator_state_values_, Context(), builder()->GetFunctionClosure(), |
314 builder()->graph()->start()); | 346 builder()->graph()->start()); |
315 | 347 |
316 return result; | 348 return result; |
317 } | 349 } |
318 | 350 |
319 | 351 |
320 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( | 352 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( |
321 AccumulatorUpdateMode update_mode) { | 353 Node** state_values, int offset, int count, int output_poke_start, |
322 return !StateValuesRequireUpdate(¶meters_state_values_, 0, | 354 int output_poke_end) { |
323 parameter_count()) && | 355 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); |
324 !StateValuesRequireUpdate(®isters_state_values_, register_base(), | 356 for (int i = 0; i < count; i++, offset++) { |
325 register_count()) && | 357 if (offset < output_poke_start || offset >= output_poke_end) { |
326 (update_mode == AccumulatorUpdateMode::kOutputInAccumulator || | 358 if ((*state_values)->InputAt(i) != values()->at(offset)) { |
327 !StateValuesRequireUpdate(&accumulator_state_values_, | 359 return false; |
328 accumulator_base(), 1)); | 360 } |
361 } | |
362 } | |
363 return true; | |
329 } | 364 } |
330 | 365 |
331 | 366 |
367 bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate( | |
368 int output_poke_offset, int output_poke_count) { | |
369 // Poke offset is relative to the top of the stack (i.e., the accumulator). | |
370 int output_poke_start = accumulator_base() - output_poke_offset; | |
371 int output_poke_end = output_poke_start + output_poke_count; | |
372 return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(), | |
373 output_poke_start, output_poke_end) && | |
374 StateValuesAreUpToDate(®isters_state_values_, register_base(), | |
375 register_count(), output_poke_start, | |
376 output_poke_end) && | |
377 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(), | |
378 1, output_poke_start, output_poke_end); | |
379 } | |
380 | |
381 | |
332 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, | 382 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, |
333 CompilationInfo* compilation_info, | 383 CompilationInfo* compilation_info, |
334 JSGraph* jsgraph) | 384 JSGraph* jsgraph) |
335 : local_zone_(local_zone), | 385 : local_zone_(local_zone), |
336 info_(compilation_info), | 386 info_(compilation_info), |
337 jsgraph_(jsgraph), | 387 jsgraph_(jsgraph), |
338 bytecode_array_(handle(info()->shared_info()->bytecode_array())), | 388 bytecode_array_(handle(info()->shared_info()->bytecode_array())), |
339 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( | 389 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( |
340 FrameStateType::kInterpretedFunction, | 390 FrameStateType::kInterpretedFunction, |
341 bytecode_array()->parameter_count(), | 391 bytecode_array()->parameter_count(), |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
414 Node* vector = BuildLoadImmutableObjectField( | 464 Node* vector = BuildLoadImmutableObjectField( |
415 shared, SharedFunctionInfo::kFeedbackVectorOffset); | 465 shared, SharedFunctionInfo::kFeedbackVectorOffset); |
416 feedback_vector_.set(vector); | 466 feedback_vector_.set(vector); |
417 } | 467 } |
418 return feedback_vector_.get(); | 468 return feedback_vector_.get(); |
419 } | 469 } |
420 | 470 |
421 | 471 |
422 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { | 472 VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) { |
423 Handle<TypeFeedbackVector> feedback_vector = info()->feedback_vector(); | 473 Handle<TypeFeedbackVector> feedback_vector = info()->feedback_vector(); |
424 FeedbackVectorSlot slot = feedback_vector->ToSlot(slot_id); | 474 FeedbackVectorSlot slot; |
475 if (slot_id >= TypeFeedbackVector::kReservedIndexCount) { | |
476 slot = feedback_vector->ToSlot(slot_id); | |
477 } | |
425 return VectorSlotPair(feedback_vector, slot); | 478 return VectorSlotPair(feedback_vector, slot); |
426 } | 479 } |
427 | 480 |
428 | 481 |
429 bool BytecodeGraphBuilder::CreateGraph(bool stack_check) { | 482 bool BytecodeGraphBuilder::CreateGraph(bool stack_check) { |
430 // Set up the basic structure of the graph. Outputs for {Start} are | 483 // Set up the basic structure of the graph. Outputs for {Start} are |
431 // the formal parameters (including the receiver) plus context and | 484 // the formal parameters (including the receiver) plus context and |
432 // closure. | 485 // closure. |
433 | 486 |
434 // Set up the basic structure of the graph. Outputs for {Start} are the formal | 487 // Set up the basic structure of the graph. Outputs for {Start} are the formal |
(...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1194 | 1247 |
1195 // Create node to perform the runtime call. | 1248 // Create node to perform the runtime call. |
1196 const Operator* call = javascript()->CallRuntime(functionId, arg_count); | 1249 const Operator* call = javascript()->CallRuntime(functionId, arg_count); |
1197 Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count); | 1250 Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count); |
1198 environment()->BindAccumulator(value, &states); | 1251 environment()->BindAccumulator(value, &states); |
1199 } | 1252 } |
1200 | 1253 |
1201 | 1254 |
1202 void BytecodeGraphBuilder::VisitCallRuntimeForPair( | 1255 void BytecodeGraphBuilder::VisitCallRuntimeForPair( |
1203 const interpreter::BytecodeArrayIterator& iterator) { | 1256 const interpreter::BytecodeArrayIterator& iterator) { |
1204 UNIMPLEMENTED(); | 1257 FrameStateBeforeAndAfter states(this, iterator); |
1258 Runtime::FunctionId functionId = | |
1259 static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0)); | |
1260 interpreter::Register first_arg = iterator.GetRegisterOperand(1); | |
1261 size_t arg_count = iterator.GetCountOperand(2); | |
1262 interpreter::Register first_return = iterator.GetRegisterOperand(3); | |
1263 | |
1264 // Create node to perform the runtime call. | |
1265 const Operator* call = javascript()->CallRuntime(functionId, arg_count); | |
1266 Node* return_pair = ProcessCallRuntimeArguments(call, first_arg, arg_count); | |
1267 environment()->BindRegistersToProjections(first_return, return_pair, 2, | |
1268 &states); | |
1205 } | 1269 } |
1206 | 1270 |
1207 | 1271 |
1208 Node* BytecodeGraphBuilder::ProcessCallNewArguments( | 1272 Node* BytecodeGraphBuilder::ProcessCallNewArguments( |
1209 const Operator* call_new_op, interpreter::Register callee, | 1273 const Operator* call_new_op, interpreter::Register callee, |
1210 interpreter::Register first_arg, size_t arity) { | 1274 interpreter::Register first_arg, size_t arity) { |
1211 Node** all = info()->zone()->NewArray<Node*>(arity); | 1275 Node** all = info()->zone()->NewArray<Node*>(arity); |
1212 all[0] = environment()->LookupRegister(callee); | 1276 all[0] = environment()->LookupRegister(callee); |
1213 int first_arg_index = first_arg.index(); | 1277 int first_arg_index = first_arg.index(); |
1214 for (int i = 1; i < static_cast<int>(arity) - 1; ++i) { | 1278 for (int i = 1; i < static_cast<int>(arity) - 1; ++i) { |
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1943 | 2007 |
1944 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | 2008 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
1945 if (environment()->IsMarkedAsUnreachable()) return; | 2009 if (environment()->IsMarkedAsUnreachable()) return; |
1946 environment()->MarkAsUnreachable(); | 2010 environment()->MarkAsUnreachable(); |
1947 exit_controls_.push_back(exit); | 2011 exit_controls_.push_back(exit); |
1948 } | 2012 } |
1949 | 2013 |
1950 } // namespace compiler | 2014 } // namespace compiler |
1951 } // namespace internal | 2015 } // namespace internal |
1952 } // namespace v8 | 2016 } // namespace v8 |
OLD | NEW |